From 07e02ff26ffd3256f3f65a0dc0328c051b598a6c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dean=20Qui=C3=B1anola?= Date: Tue, 3 Feb 2026 20:42:54 -0800 Subject: [PATCH 01/10] refactor!: release-please should bump to a version on breaking change --- release-please-config.json | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/release-please-config.json b/release-please-config.json index 8a32359..beb9adb 100644 --- a/release-please-config.json +++ b/release-please-config.json @@ -18,7 +18,5 @@ ] } }, - "bootstrap-sha": "040347b5859ccc7ed230c398721e16d651fae887", - "bump-minor-pre-major": true, - "bump-patch-for-minor-pre-major": true + "bootstrap-sha": "040347b5859ccc7ed230c398721e16d651fae887" } From 6ecbdf23edfd434b49ea81f27499a1d541a793a4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dean=20Qui=C3=B1anola?= Date: Tue, 3 Feb 2026 21:06:32 -0800 Subject: [PATCH 02/10] ci: remove deploy workflow, integrate with main CI/CD pipeline Deploy workflow functionality has been integrated into ci.yml with workflow_dispatch support. Updates documentation to reflect unified CI/CD approach. --- .github/workflows/deploy.yml | 143 ----------------------------------- CLAUDE.md | 4 +- 2 files changed, 2 insertions(+), 145 deletions(-) delete mode 100644 .github/workflows/deploy.yml diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml deleted file mode 100644 index 847028e..0000000 --- a/.github/workflows/deploy.yml +++ /dev/null @@ -1,143 +0,0 @@ -name: Deploy - -on: - workflow_dispatch: - inputs: - tag: - description: 'Docker tag to use' - required: true - default: 'manual' - type: string - skip_tests: - description: 'Skip test suite (emergency deployments only)' - required: false - default: false - type: boolean - -env: - REGISTRY: docker.io - IMAGE_NAME: runpod/flash - -jobs: - test: - runs-on: ubuntu-latest - if: ${{ !inputs.skip_tests }} - steps: - - name: Checkout repository - uses: actions/checkout@v4 - with: - fetch-depth: 0 - - - name: Set up Python - uses: actions/setup-python@v5 - with: - python-version: "3.11" - - - name: Set up uv - uses: astral-sh/setup-uv@v4 - with: - enable-cache: true - - - name: Setup dependencies - run: make setup - - - name: Run quality checks - run: make quality-check - - docker: - runs-on: ubuntu-latest - needs: [test] - if: ${{ always() && (success() || inputs.skip_tests) }} - steps: - - name: Clear Space - run: | - rm -rf /usr/share/dotnet - rm -rf /opt/ghc - rm -rf "/usr/local/share/boost" - rm -rf "$AGENT_TOOLSDIRECTORY" - - - 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: Login to Docker Hub - uses: docker/login-action@v3 - with: - registry: ${{ env.REGISTRY }} - username: ${{ secrets.DOCKERHUB_USERNAME }} - password: ${{ secrets.DOCKERHUB_TOKEN }} - - - name: Set up uv - uses: astral-sh/setup-uv@v4 - with: - enable-cache: true - - - name: Setup dependencies - run: uv sync - - - name: Build and push GPU Docker image - uses: docker/build-push-action@v6 - with: - context: . - file: ./Dockerfile - platforms: linux/amd64,linux/arm64 - push: true - tags: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:${{ inputs.tag }} - cache-from: type=gha - cache-to: type=gha,mode=max - - - name: Build and push CPU Docker image - uses: docker/build-push-action@v6 - with: - context: . - file: ./Dockerfile-cpu - platforms: linux/amd64,linux/arm64 - push: true - tags: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}-cpu:${{ inputs.tag }} - cache-from: type=gha - cache-to: type=gha,mode=max - - - name: Build and push Load Balancer Docker image - uses: docker/build-push-action@v6 - with: - context: . - file: ./Dockerfile-lb - platforms: linux/amd64,linux/arm64 - push: true - tags: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}-lb:${{ inputs.tag }} - cache-from: type=gha - cache-to: type=gha,mode=max - - - name: Build and push CPU Load Balancer Docker image - uses: docker/build-push-action@v6 - with: - context: . - file: ./Dockerfile-lb-cpu - platforms: linux/amd64,linux/arm64 - push: true - tags: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}-lb-cpu:${{ inputs.tag }} - cache-from: type=gha - cache-to: type=gha,mode=max - - - name: Summary - run: | - echo "🚀 **Deployment Complete**" >> $GITHUB_STEP_SUMMARY - echo "" >> $GITHUB_STEP_SUMMARY - echo "**Images pushed:**" >> $GITHUB_STEP_SUMMARY - echo "- \`${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:${{ inputs.tag }}\`" >> $GITHUB_STEP_SUMMARY - echo "- \`${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}-cpu:${{ inputs.tag }}\`" >> $GITHUB_STEP_SUMMARY - echo "- \`${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}-lb:${{ inputs.tag }}\`" >> $GITHUB_STEP_SUMMARY - echo "- \`${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}-lb-cpu:${{ inputs.tag }}\`" >> $GITHUB_STEP_SUMMARY - echo "" >> $GITHUB_STEP_SUMMARY - if [ "${{ inputs.skip_tests }}" = "true" ]; then - echo "⚠️ **Tests were skipped** (emergency deployment)" >> $GITHUB_STEP_SUMMARY - else - echo "✅ **All tests passed**" >> $GITHUB_STEP_SUMMARY - fi \ No newline at end of file diff --git a/CLAUDE.md b/CLAUDE.md index d0bb548..a15c45c 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -267,9 +267,9 @@ gpu_config = LiveServerless( - Runs tests and linting on PRs and pushes to main - **Local execution testing**: Automatically tests all `test_*.json` files in src directory to validate handler functionality - Manages releases via `release-please` on main branch - - Builds and pushes `:dev` tagged images on main branch pushes + - Builds and pushes `:main` tagged images on main branch pushes - Builds and pushes production images with semantic versioning on releases -- **Deploy** (`.github/workflows/deploy.yml`): Manual deployment workflow for custom Docker tags and emergency deployments + - Supports manual triggering via `workflow_dispatch` for ad-hoc runs ### Required Secrets Configure these in GitHub repository settings: From 831f965b69e6c44e175ad08e45ec535cfee5d0f1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dean=20Qui=C3=B1anola?= Date: Tue, 3 Feb 2026 21:20:40 -0800 Subject: [PATCH 03/10] ci: optimize GitHub Actions workflow for 50% faster PR validation MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Python matrix: 5 versions → 2 on PRs (60% reduction), 5 on main/release - Test execution: Consolidated to single coverage run on PRs (66% reduction) - Docker builds: Parallelize with lint dependency instead of test (saves ~3 min) - Disk cleanup: Right-size for image type (CPU: manual, GPU: aggressive) - Validation gate: Centralized quality control before release - Cache optimization: Add explicit cache-dependency-glob for uv Expected improvement: PR validation 12-17 min → 6-8 min (50-60% faster) --- .github/workflows/ci.yml | 72 +++++++++++++++++++++++++--------------- 1 file changed, 46 insertions(+), 26 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 959d923..77bc9e1 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -21,8 +21,8 @@ jobs: runs-on: ubuntu-latest strategy: matrix: - python-version: ['3.10', '3.11', '3.12', '3.13', '3.14'] - + python-version: ${{ github.event_name == 'pull_request' && fromJSON('["3.11", "3.12"]') || fromJSON('["3.10", "3.11", "3.12", "3.13", "3.14"]') }} + steps: - name: Checkout repository uses: actions/checkout@v4 @@ -38,19 +38,27 @@ jobs: uses: astral-sh/setup-uv@v4 with: enable-cache: true + cache-dependency-glob: | + **/pyproject.toml + **/uv.lock - name: Setup dependencies run: make setup - - name: Run unit tests + - name: Run all tests with coverage + run: make test-coverage + + - name: Test handler locally with test JSON files + run: make test-handler + + - name: Run unit tests separately (main branch only) + if: github.ref == 'refs/heads/main' run: make test-unit - - name: Run integration tests + - name: Run integration tests separately (main branch only) + if: github.ref == 'refs/heads/main' run: make test-integration - - name: Run all tests with coverage - run: make test-coverage - lint: runs-on: ubuntu-latest steps: @@ -75,7 +83,7 @@ jobs: docker-test: runs-on: ubuntu-latest - needs: [test, lint] + needs: [lint] steps: - name: Clear Space # Note: Manual cleanup sufficient for CPU images (python:3.12-slim base ~150MB) @@ -126,7 +134,7 @@ jobs: docker-test-lb: runs-on: ubuntu-latest - needs: [test, lint] + needs: [lint] steps: - name: Free Disk Space uses: jlumbroso/free-disk-space@v1.3.1 @@ -176,20 +184,16 @@ jobs: docker-test-lb-cpu: runs-on: ubuntu-latest - needs: [test, lint] + 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 + - 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 @@ -224,9 +228,25 @@ jobs: cache-to: type=gha,mode=max load: true - release: + docker-validation: runs-on: ubuntu-latest needs: [test, lint, docker-test, docker-test-lb, docker-test-lb-cpu] + if: always() + steps: + - name: Check all jobs succeeded + run: | + if [[ "${{ needs.test.result }}" != "success" ]] || \ + [[ "${{ needs.lint.result }}" != "success" ]] || \ + [[ "${{ needs.docker-test.result }}" != "success" ]] || \ + [[ "${{ needs.docker-test-lb.result }}" != "success" ]] || \ + [[ "${{ needs.docker-test-lb-cpu.result }}" != "success" ]]; then + echo "One or more quality checks failed" + exit 1 + fi + + release: + runs-on: ubuntu-latest + needs: [docker-validation] if: github.ref == 'refs/heads/main' outputs: release_created: ${{ steps.release.outputs.release_created }} @@ -246,7 +266,7 @@ jobs: docker-main-gpu: runs-on: ubuntu-latest - needs: [test, lint, docker-test, release] + needs: [docker-validation, release] if: github.ref == 'refs/heads/main' && github.event_name == 'push' && !needs.release.outputs.release_created steps: - name: Free Disk Space @@ -303,7 +323,7 @@ jobs: docker-main-cpu: runs-on: ubuntu-latest - needs: [test, lint, docker-test, release] + needs: [docker-validation, release] if: github.ref == 'refs/heads/main' && github.event_name == 'push' && !needs.release.outputs.release_created steps: - name: Clear Space @@ -354,7 +374,7 @@ jobs: docker-main-lb: runs-on: ubuntu-latest - needs: [test, lint, docker-test, docker-test-lb, release] + needs: [docker-validation, release] if: github.ref == 'refs/heads/main' && github.event_name == 'push' && !needs.release.outputs.release_created steps: - name: Free Disk Space @@ -411,7 +431,7 @@ jobs: docker-main-lb-cpu: runs-on: ubuntu-latest - needs: [test, lint, docker-test, docker-test-lb-cpu, release] + needs: [docker-validation, release] if: github.ref == 'refs/heads/main' && github.event_name == 'push' && !needs.release.outputs.release_created steps: - name: Free Disk Space From a5661524097351ad80c89bb3abca041700e03c80 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dean=20Qui=C3=B1anola?= Date: Tue, 3 Feb 2026 21:28:06 -0800 Subject: [PATCH 04/10] test(unpack_volume): mock sleep in exception propagation test Mock the sleep function in test_maybe_unpack_propagates_exceptions to prevent 60-second pause during test execution. The test was triggering retry logic with real 30-second sleep calls. Matches pattern already used in test_maybe_unpack_logs_error_on_failure. Test now completes in <1 second instead of ~60 seconds. --- tests/unit/test_unpack_volume.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/tests/unit/test_unpack_volume.py b/tests/unit/test_unpack_volume.py index ad14416..b33943b 100644 --- a/tests/unit/test_unpack_volume.py +++ b/tests/unit/test_unpack_volume.py @@ -396,9 +396,10 @@ def test_maybe_unpack_skips_when_should_not_unpack(self, mock_unpack, mock_shoul mock_should_unpack.assert_called_once() mock_unpack.assert_not_called() + @patch("unpack_volume.sleep") @patch("unpack_volume._should_unpack_from_volume") @patch("unpack_volume.unpack_app_from_volume") - def test_maybe_unpack_propagates_exceptions(self, mock_unpack, mock_should_unpack): + def test_maybe_unpack_propagates_exceptions(self, mock_unpack, mock_should_unpack, mock_sleep): """Test that exceptions during unpacking are propagated.""" mock_should_unpack.return_value = True mock_unpack.side_effect = FileNotFoundError("Artifact not found") From 89119647988d79348f9d209c83171a876eda6557 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dean=20Qui=C3=B1anola?= Date: Tue, 3 Feb 2026 21:30:50 -0800 Subject: [PATCH 05/10] test: enable parallel test execution with pytest-xdist Add pytest-xdist dependency and configure all test targets to run in parallel using auto-detected worker count with loadscope distribution strategy. Reduces test execution time while maintaining test isolation via fixture-aware scheduling. - Add pytest-xdist>=3.5.0 to dev dependencies - Update test, test-unit, and test-coverage targets to use -n auto --dist loadscope - All 240 tests pass with parallel execution (12 workers on this system) --- Makefile | 10 +++++----- pyproject.toml | 1 + uv.lock | 24 ++++++++++++++++++++++++ 3 files changed, 30 insertions(+), 5 deletions(-) diff --git a/Makefile b/Makefile index 500c833..3524ac8 100644 --- a/Makefile +++ b/Makefile @@ -131,17 +131,17 @@ build-wip-lb-cpu: setup # Build and push LB CPU image (multi-platform) . --push # Test commands -test: # Run all tests - uv run pytest tests/ -v +test: # Run all tests in parallel + uv run pytest tests/ -v -n auto --dist loadscope test-unit: # Run unit tests only - uv run pytest tests/unit/ -v -m "not integration" + uv run pytest tests/unit/ -v -m "not integration" -n auto --dist loadscope test-integration: # Run integration tests only uv run pytest tests/integration/ -v -m integration -test-coverage: # Run tests with coverage report - uv run pytest tests/ -v --cov=handler --cov=remote_execution --cov-report=term-missing +test-coverage: # Run tests with coverage report (parallel) + uv run pytest tests/ -v -n auto --dist loadscope --cov=handler --cov=remote_execution --cov-report=term-missing test-fast: # Run tests with fast-fail mode uv run pytest tests/ -v -x --tb=short diff --git a/pyproject.toml b/pyproject.toml index 20cae20..c11e140 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -23,6 +23,7 @@ dev = [ "pytest-mock>=3.14.0", "pytest-cov>=6.0.0", "pytest-asyncio>=0.24.0", + "pytest-xdist>=3.5.0", "ruff>=0.8.0", "mypy>=1.11.0", "types-requests>=2.25.0", diff --git a/uv.lock b/uv.lock index 9fcb145..5278c1a 100644 --- a/uv.lock +++ b/uv.lock @@ -925,6 +925,15 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/8a/0e/97c33bf5009bdbac74fd2beace167cab3f978feb69cc36f1ef79360d6c4e/exceptiongroup-1.3.1-py3-none-any.whl", hash = "sha256:a7a39a3bd276781e98394987d3a5701d0c4edffb633bb7a5144577f82c773598", size = 16740 }, ] +[[package]] +name = "execnet" +version = "2.1.2" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/bf/89/780e11f9588d9e7128a3f87788354c7946a9cbb1401ad38a48c4db9a4f07/execnet-2.1.2.tar.gz", hash = "sha256:63d83bfdd9a23e35b9c6a3261412324f964c2ec8dcd8d3c6916ee9373e0befcd", size = 166622 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/ab/84/02fc1827e8cdded4aa65baef11296a9bbe595c474f0d6d758af082d849fd/execnet-2.1.2-py3-none-any.whl", hash = "sha256:67fba928dd5a544b783f6056f449e5e3931a5c378b128bc18501f7ea79e296ec", size = 40708 }, +] + [[package]] name = "fastapi" version = "0.128.0" @@ -2573,6 +2582,19 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/5a/cc/06253936f4a7fa2e0f48dfe6d851d9c56df896a9ab09ac019d70b760619c/pytest_mock-3.15.1-py3-none-any.whl", hash = "sha256:0a25e2eb88fe5168d535041d09a4529a188176ae608a6d249ee65abc0949630d", size = 10095 }, ] +[[package]] +name = "pytest-xdist" +version = "3.8.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "execnet" }, + { name = "pytest" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/78/b4/439b179d1ff526791eb921115fca8e44e596a13efeda518b9d845a619450/pytest_xdist-3.8.0.tar.gz", hash = "sha256:7e578125ec9bc6050861aa93f2d59f1d8d085595d6551c2c90b6f4fad8d3a9f1", size = 88069 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/ca/31/d4e37e9e550c2b92a9cbc2e4d0b7420a27224968580b5a447f420847c975/pytest_xdist-3.8.0-py3-none-any.whl", hash = "sha256:202ca578cfeb7370784a8c33d6d05bc6e13b4f25b5053c30a152269fd10f0b88", size = 46396 }, +] + [[package]] name = "python-dateutil" version = "2.9.0.post0" @@ -3687,6 +3709,7 @@ dev = [ { name = "pytest-asyncio" }, { name = "pytest-cov" }, { name = "pytest-mock" }, + { name = "pytest-xdist" }, { name = "rich" }, { name = "ruff" }, { name = "typer" }, @@ -3715,6 +3738,7 @@ dev = [ { name = "pytest-asyncio", specifier = ">=0.24.0" }, { name = "pytest-cov", specifier = ">=6.0.0" }, { name = "pytest-mock", specifier = ">=3.14.0" }, + { name = "pytest-xdist", specifier = ">=3.5.0" }, { name = "rich", specifier = ">=14.0.0" }, { name = "ruff", specifier = ">=0.8.0" }, { name = "typer", specifier = ">=0.12.0" }, From 7a4e0e328fff133bf0a380e2760c7f4e76a8acf2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dean=20Qui=C3=B1anola?= Date: Tue, 3 Feb 2026 21:36:40 -0800 Subject: [PATCH 06/10] fix: defer runpod import to allow local handler testing Move the import runpod statement into the if __name__ == "__main__" block to defer it until actually running the handler on RunPod's serverless platform. This allows the handler module to be imported during local testing without requiring the runpod package to be available in the test environment. The runpod.serverless.start() call is only executed when the handler runs directly on the platform. Fixes: Handler test failures when runpod package is unavailable during local execution of test_handler.sh script. --- src/handler.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/handler.py b/src/handler.py index e05df95..5066690 100644 --- a/src/handler.py +++ b/src/handler.py @@ -1,4 +1,3 @@ -import runpod from typing import Dict, Any from runpod_flash.protos.remote_execution import FunctionRequest, FunctionResponse @@ -34,6 +33,8 @@ async def handler(event: Dict[str, Any]) -> Dict[str, Any]: return output.model_dump() # type: ignore[no-any-return] -# Start the RunPod serverless handler +# Start the RunPod serverless handler (only available on RunPod platform) if __name__ == "__main__": + import runpod + runpod.serverless.start({"handler": handler}) From 2efeb34168e38ec83b7eb4bc733a71b742fe2b07 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dean=20Qui=C3=B1anola?= Date: Tue, 3 Feb 2026 21:41:22 -0800 Subject: [PATCH 07/10] fix: use uv run in test-handler.sh to ensure dependencies are available Changed test-handler.sh to always use 'uv run' instead of trying to detect whether system python is available. The previous logic checked for system python and would use it directly, but in CI environments like GitHub Actions, the system python doesn't have the project dependencies installed. By using 'uv run', we ensure the virtual environment with all dependencies is used, consistent with how the rest of the project runs tests and builds. --- src/test-handler.sh | 12 +++--------- 1 file changed, 3 insertions(+), 9 deletions(-) diff --git a/src/test-handler.sh b/src/test-handler.sh index 303e3ec..73a42af 100755 --- a/src/test-handler.sh +++ b/src/test-handler.sh @@ -16,15 +16,9 @@ for test_file in tests/test_*.json; do echo "Testing with $test_file..." # Run the test and capture output - # In Docker: python is available and has system-installed packages - # Locally: use uv run to manage dependencies - if command -v python &> /dev/null; then - output=$(python handler.py --test_input "$(cat "$test_file")" 2>&1) - exit_code=$? - else - output=$(uv run python3 handler.py --test_input "$(cat "$test_file")" 2>&1) - exit_code=$? - fi + # Use uv run to ensure all dependencies are available + output=$(uv run python handler.py --test_input "$(cat "$test_file")" 2>&1) + exit_code=$? if [ $exit_code -eq 0 ]; then echo "✓ $test_file: PASSED" From a47a2f1cc9617d9fcff7900af3fc611d61fa3654 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dean=20Qui=C3=B1anola?= Date: Tue, 3 Feb 2026 21:58:38 -0800 Subject: [PATCH 08/10] ci: remove test-handler from non-Docker CI job The test-handler.sh script requires root access for apt-get operations to install system dependencies. This works in Docker containers but fails in the GitHub Actions runner environment. Keep handler tests running only in Docker jobs where they have proper permissions. --- .github/workflows/ci.yml | 3 --- 1 file changed, 3 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 77bc9e1..f9ebab7 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -48,9 +48,6 @@ jobs: - name: Run all tests with coverage run: make test-coverage - - name: Test handler locally with test JSON files - run: make test-handler - - name: Run unit tests separately (main branch only) if: github.ref == 'refs/heads/main' run: make test-unit From a70d62330d8dc105ed60539a8a6fa8a67eeb7cd6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dean=20Qui=C3=B1anola?= Date: Tue, 3 Feb 2026 22:06:19 -0800 Subject: [PATCH 09/10] ci: remove docker-main-* jobs to speed up CI by 10-15 minutes Removed all four docker-main-* jobs (gpu, cpu, lb, lb-cpu) that built :main tagged images on every main branch push. Docker images are now only built during releases with semantic versioning. This simplifies the workflow and reduces GitHub Actions minutes usage. --- .github/workflows/ci.yml | 222 --------------------------------------- 1 file changed, 222 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index f9ebab7..d61c13d 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -261,228 +261,6 @@ jobs: with: token: ${{ steps.app-token.outputs.token }} - docker-main-gpu: - runs-on: ubuntu-latest - needs: [docker-validation, release] - if: github.ref == 'refs/heads/main' && github.event_name == 'push' && !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 - 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: Login to Docker Hub - uses: docker/login-action@v3 - with: - registry: ${{ env.REGISTRY }} - username: ${{ secrets.DOCKERHUB_USERNAME }} - password: ${{ secrets.DOCKERHUB_TOKEN }} - - - name: Set up uv - uses: astral-sh/setup-uv@v4 - with: - enable-cache: true - - - name: Setup dependencies - run: uv sync - - - name: Build and push GPU Docker image (main) - uses: docker/build-push-action@v6 - with: - context: . - file: ./Dockerfile - platforms: linux/amd64,linux/arm64 - push: true - tags: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:main - cache-from: type=gha - cache-to: type=gha,mode=max - - docker-main-cpu: - runs-on: ubuntu-latest - needs: [docker-validation, release] - if: github.ref == 'refs/heads/main' && github.event_name == 'push' && !needs.release.outputs.release_created - steps: - - name: Clear Space - 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: Login to Docker Hub - uses: docker/login-action@v3 - with: - registry: ${{ env.REGISTRY }} - username: ${{ secrets.DOCKERHUB_USERNAME }} - password: ${{ secrets.DOCKERHUB_TOKEN }} - - - name: Set up uv - uses: astral-sh/setup-uv@v4 - with: - enable-cache: true - - - name: Setup dependencies - run: uv sync - - - name: Build and push CPU Docker image (main) - uses: docker/build-push-action@v6 - with: - context: . - file: ./Dockerfile-cpu - platforms: linux/amd64,linux/arm64 - push: true - tags: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}-cpu:main - cache-from: type=gha - cache-to: type=gha,mode=max - - docker-main-lb: - runs-on: ubuntu-latest - needs: [docker-validation, release] - if: github.ref == 'refs/heads/main' && github.event_name == 'push' && !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 - 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: Login to Docker Hub - uses: docker/login-action@v3 - with: - registry: ${{ env.REGISTRY }} - username: ${{ secrets.DOCKERHUB_USERNAME }} - password: ${{ secrets.DOCKERHUB_TOKEN }} - - - name: Set up uv - uses: astral-sh/setup-uv@v4 - with: - enable-cache: true - - - name: Setup dependencies - run: uv sync - - - name: Build and push Load Balancer Docker image (main) - uses: docker/build-push-action@v6 - with: - context: . - file: ./Dockerfile-lb - platforms: linux/amd64,linux/arm64 - push: true - tags: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}-lb:main - cache-from: type=gha - cache-to: type=gha,mode=max - - docker-main-lb-cpu: - runs-on: ubuntu-latest - needs: [docker-validation, release] - if: github.ref == 'refs/heads/main' && github.event_name == 'push' && !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 - 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: Login to Docker Hub - uses: docker/login-action@v3 - with: - registry: ${{ env.REGISTRY }} - username: ${{ secrets.DOCKERHUB_USERNAME }} - password: ${{ secrets.DOCKERHUB_TOKEN }} - - - name: Set up uv - uses: astral-sh/setup-uv@v4 - with: - enable-cache: true - - - name: Setup dependencies - run: uv sync - - - name: Build and push CPU Load Balancer Docker image (main) - uses: docker/build-push-action@v6 - with: - context: . - file: ./Dockerfile-lb-cpu - platforms: linux/amd64,linux/arm64 - push: true - tags: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}-lb-cpu:main - cache-from: type=gha - cache-to: type=gha,mode=max - docker-prod-gpu: runs-on: ubuntu-latest needs: [release] From 106a89e66f2a2a13d90d4210fda39ab1336ea914 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dean=20Qui=C3=B1anola?= Date: Tue, 3 Feb 2026 22:41:30 -0800 Subject: [PATCH 10/10] fix: use system Python in Docker for test-handler.sh Fixed test_dependencies.json CI failure by detecting Docker environment and using system Python instead of uv run. This ensures test handler uses the same Python environment as dependency_installer.py, which installs packages to system Python with --system flag in Docker. In Docker: uses system Python with pre-installed packages In local: uses uv run for proper dependency management --- src/test-handler.sh | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/src/test-handler.sh b/src/test-handler.sh index 73a42af..34aa26d 100755 --- a/src/test-handler.sh +++ b/src/test-handler.sh @@ -11,14 +11,20 @@ for test_file in tests/test_*.json; do echo "No test_*.json files found" exit 1 fi - + test_count=$((test_count + 1)) echo "Testing with $test_file..." - - # Run the test and capture output - # Use uv run to ensure all dependencies are available - output=$(uv run python handler.py --test_input "$(cat "$test_file")" 2>&1) - exit_code=$? + + # Detect if running in Docker + if [ -f /.dockerenv ]; then + # Docker: use system python with pre-installed packages + output=$(python handler.py --test_input "$(cat "$test_file")" 2>&1) + exit_code=$? + else + # Local: use uv run to manage dependencies + output=$(uv run python handler.py --test_input "$(cat "$test_file")" 2>&1) + exit_code=$? + fi if [ $exit_code -eq 0 ]; then echo "✓ $test_file: PASSED"