feat(web): merge DigitalOcean release announcement updates #314
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: CI | |
| on: | |
| push: | |
| branches: [main] | |
| pull_request: | |
| permissions: | |
| contents: read | |
| security-events: write | |
| env: | |
| PLANO_DOCKER_IMAGE: katanemo/plano:e2e | |
| DOCKER_IMAGE: katanemo/plano | |
| jobs: | |
| # ────────────────────────────────────────────── | |
| # Pre-commit (fmt, clippy, cargo test, black, yaml) | |
| # ────────────────────────────────────────────── | |
| pre-commit: | |
| runs-on: ubuntu-latest | |
| steps: | |
| - uses: actions/checkout@v6 | |
| - uses: actions/setup-python@v6 | |
| - uses: pre-commit/action@v3.0.1 | |
| # ────────────────────────────────────────────── | |
| # Plano tools (CLI) tests — no Docker needed | |
| # ────────────────────────────────────────────── | |
| plano-tools-tests: | |
| runs-on: ubuntu-latest-m | |
| defaults: | |
| run: | |
| working-directory: ./cli | |
| steps: | |
| - uses: actions/checkout@v6 | |
| - name: Set up Python | |
| uses: actions/setup-python@v6 | |
| with: | |
| python-version: "3.14" | |
| - name: Install uv | |
| run: curl -LsSf https://astral.sh/uv/install.sh | sh | |
| - name: Install plano tools | |
| run: uv sync --extra dev | |
| - name: Sync CLI templates to demos | |
| if: github.event_name == 'push' && github.ref == 'refs/heads/main' | |
| run: uv run python -m planoai.template_sync | |
| - name: Run tests | |
| run: uv run pytest | |
| # ────────────────────────────────────────────── | |
| # Native mode smoke test — build from source & start natively | |
| # ────────────────────────────────────────────── | |
| native-smoke-test: | |
| runs-on: ubuntu-latest | |
| steps: | |
| - name: Checkout code | |
| uses: actions/checkout@v6 | |
| - name: Set up Python | |
| uses: actions/setup-python@v6 | |
| with: | |
| python-version: "3.12" | |
| - name: Install uv | |
| run: curl -LsSf https://astral.sh/uv/install.sh | sh | |
| - name: Install Rust | |
| uses: dtolnay/rust-toolchain@stable | |
| with: | |
| targets: wasm32-wasip1 | |
| - name: Install planoai CLI | |
| working-directory: ./cli | |
| run: | | |
| uv sync | |
| uv tool install . | |
| - name: Build native binaries | |
| run: planoai build | |
| - name: Start plano natively | |
| env: | |
| OPENAI_API_KEY: test-key-not-used | |
| run: planoai up tests/e2e/config_native_smoke.yaml | |
| - name: Health check | |
| run: | | |
| for i in $(seq 1 30); do | |
| if curl -sf http://localhost:12000/healthz > /dev/null 2>&1; then | |
| echo "Health check passed" | |
| exit 0 | |
| fi | |
| sleep 1 | |
| done | |
| echo "Health check failed after 30s" | |
| cat ~/.plano/run/logs/envoy.log || true | |
| cat ~/.plano/run/logs/brightstaff.log || true | |
| exit 1 | |
| - name: Stop plano | |
| if: always() | |
| run: planoai down || true | |
| # ────────────────────────────────────────────── | |
| # Single Docker build — shared by all downstream jobs | |
| # ────────────────────────────────────────────── | |
| docker-build: | |
| runs-on: ubuntu-latest | |
| steps: | |
| - name: Checkout code | |
| uses: actions/checkout@v6 | |
| - name: Free disk space on runner | |
| run: | | |
| sudo rm -rf /usr/share/dotnet /usr/local/lib/android /opt/ghc | |
| docker system prune -af || true | |
| docker volume prune -f || true | |
| - name: Set up Docker Buildx | |
| uses: docker/setup-buildx-action@v3 | |
| - name: Build plano image (with GHA cache) | |
| uses: docker/build-push-action@v6 | |
| with: | |
| context: . | |
| file: Dockerfile | |
| load: true | |
| tags: | | |
| ${{ env.PLANO_DOCKER_IMAGE }} | |
| ${{ env.DOCKER_IMAGE }}:0.4.16 | |
| ${{ env.DOCKER_IMAGE }}:latest | |
| cache-from: type=gha | |
| cache-to: type=gha,mode=max | |
| - name: Save image as artifact | |
| run: docker save ${{ env.PLANO_DOCKER_IMAGE }} ${{ env.DOCKER_IMAGE }}:0.4.16 ${{ env.DOCKER_IMAGE }}:latest -o /tmp/plano-image.tar | |
| - name: Upload image artifact | |
| uses: actions/upload-artifact@v6 | |
| with: | |
| name: plano-image | |
| path: /tmp/plano-image.tar | |
| retention-days: 1 | |
| # ────────────────────────────────────────────── | |
| # Validate plano config | |
| # ────────────────────────────────────────────── | |
| validate-config: | |
| runs-on: ubuntu-latest | |
| steps: | |
| - name: Checkout code | |
| uses: actions/checkout@v6 | |
| - name: Set up Python | |
| uses: actions/setup-python@v6 | |
| with: | |
| python-version: "3.14" | |
| - name: Install planoai | |
| run: pip install -e ./cli | |
| - name: Validate plano config | |
| run: bash config/validate_plano_config.sh | |
| # ────────────────────────────────────────────── | |
| # Docker security scan (Trivy) | |
| # ────────────────────────────────────────────── | |
| security-scan: | |
| needs: docker-build | |
| runs-on: ubuntu-latest | |
| steps: | |
| - name: Checkout code | |
| uses: actions/checkout@v6 | |
| - name: Download plano image | |
| uses: actions/download-artifact@v7 | |
| with: | |
| name: plano-image | |
| path: /tmp | |
| - name: Load plano image | |
| run: docker load -i /tmp/plano-image.tar | |
| - name: Run Trivy vulnerability scanner | |
| uses: aquasecurity/trivy-action@master | |
| with: | |
| image-ref: ${{ env.DOCKER_IMAGE }}:latest | |
| format: table | |
| exit-code: ${{ github.event_name == 'pull_request' && '1' || '0' }} | |
| ignore-unfixed: true | |
| severity: CRITICAL,HIGH | |
| - name: Run Trivy scanner (SARIF for GitHub Security tab) | |
| if: always() | |
| uses: aquasecurity/trivy-action@master | |
| with: | |
| image-ref: ${{ env.DOCKER_IMAGE }}:latest | |
| format: sarif | |
| output: trivy-results.sarif | |
| ignore-unfixed: true | |
| severity: CRITICAL,HIGH | |
| - name: Upload Trivy results to GitHub Security tab | |
| if: always() | |
| uses: github/codeql-action/upload-sarif@v3 | |
| with: | |
| sarif_file: trivy-results.sarif | |
| # ────────────────────────────────────────────── | |
| # E2E: prompt_gateway tests | |
| # ────────────────────────────────────────────── | |
| test-prompt-gateway: | |
| needs: docker-build | |
| runs-on: ubuntu-latest | |
| steps: | |
| - name: Checkout code | |
| uses: actions/checkout@v6 | |
| - name: Free disk space on runner | |
| run: | | |
| sudo rm -rf /usr/share/dotnet /usr/local/lib/android /opt/ghc | |
| docker system prune -af || true | |
| docker volume prune -f || true | |
| - name: Download plano image | |
| uses: actions/download-artifact@v7 | |
| with: | |
| name: plano-image | |
| path: /tmp | |
| - name: Load plano image | |
| run: docker load -i /tmp/plano-image.tar | |
| - name: Set up Python | |
| uses: actions/setup-python@v6 | |
| with: | |
| python-version: "3.14" | |
| - name: Install uv | |
| uses: astral-sh/setup-uv@v7 | |
| with: | |
| enable-cache: true | |
| cache-dependency-glob: | | |
| tests/e2e/uv.lock | |
| cli/uv.lock | |
| - name: Run prompt_gateway tests | |
| env: | |
| OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }} | |
| MISTRAL_API_KEY: ${{ secrets.MISTRAL_API_KEY }} | |
| GROQ_API_KEY: ${{ secrets.GROQ_API_KEY }} | |
| ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }} | |
| AZURE_API_KEY: ${{ secrets.AZURE_API_KEY }} | |
| AWS_BEARER_TOKEN_BEDROCK: ${{ secrets.AWS_BEARER_TOKEN_BEDROCK }} | |
| GROK_API_KEY: ${{ secrets.GROK_API_KEY }} | |
| run: | | |
| cd tests/e2e && bash run_prompt_gateway_tests.sh | |
| # ────────────────────────────────────────────── | |
| # E2E: model_alias_routing tests | |
| # ────────────────────────────────────────────── | |
| test-model-alias-routing: | |
| needs: docker-build | |
| runs-on: ubuntu-latest | |
| steps: | |
| - name: Checkout code | |
| uses: actions/checkout@v6 | |
| - name: Free disk space on runner | |
| run: | | |
| sudo rm -rf /usr/share/dotnet /usr/local/lib/android /opt/ghc | |
| docker system prune -af || true | |
| docker volume prune -f || true | |
| - name: Download plano image | |
| uses: actions/download-artifact@v7 | |
| with: | |
| name: plano-image | |
| path: /tmp | |
| - name: Load plano image | |
| run: docker load -i /tmp/plano-image.tar | |
| - name: Set up Python | |
| uses: actions/setup-python@v6 | |
| with: | |
| python-version: "3.14" | |
| - name: Install uv | |
| uses: astral-sh/setup-uv@v7 | |
| with: | |
| enable-cache: true | |
| cache-dependency-glob: | | |
| tests/e2e/uv.lock | |
| cli/uv.lock | |
| - name: Run model alias routing tests | |
| env: | |
| OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }} | |
| MISTRAL_API_KEY: ${{ secrets.MISTRAL_API_KEY }} | |
| GROQ_API_KEY: ${{ secrets.GROQ_API_KEY }} | |
| ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }} | |
| AZURE_API_KEY: ${{ secrets.AZURE_API_KEY }} | |
| AWS_BEARER_TOKEN_BEDROCK: ${{ secrets.AWS_BEARER_TOKEN_BEDROCK }} | |
| GROK_API_KEY: ${{ secrets.GROK_API_KEY }} | |
| run: | | |
| cd tests/e2e && bash run_model_alias_tests.sh | |
| # ────────────────────────────────────────────── | |
| # E2E: responses API with state tests | |
| # ────────────────────────────────────────────── | |
| test-responses-api-with-state: | |
| needs: docker-build | |
| runs-on: ubuntu-latest | |
| steps: | |
| - name: Checkout code | |
| uses: actions/checkout@v6 | |
| - name: Free disk space on runner | |
| run: | | |
| sudo rm -rf /usr/share/dotnet /usr/local/lib/android /opt/ghc | |
| docker system prune -af || true | |
| docker volume prune -f || true | |
| - name: Download plano image | |
| uses: actions/download-artifact@v7 | |
| with: | |
| name: plano-image | |
| path: /tmp | |
| - name: Load plano image | |
| run: docker load -i /tmp/plano-image.tar | |
| - name: Set up Python | |
| uses: actions/setup-python@v6 | |
| with: | |
| python-version: "3.14" | |
| - name: Install uv | |
| uses: astral-sh/setup-uv@v7 | |
| with: | |
| enable-cache: true | |
| cache-dependency-glob: | | |
| tests/e2e/uv.lock | |
| cli/uv.lock | |
| - name: Run responses API with state tests | |
| env: | |
| OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }} | |
| MISTRAL_API_KEY: ${{ secrets.MISTRAL_API_KEY }} | |
| GROQ_API_KEY: ${{ secrets.GROQ_API_KEY }} | |
| ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }} | |
| AZURE_API_KEY: ${{ secrets.AZURE_API_KEY }} | |
| AWS_BEARER_TOKEN_BEDROCK: ${{ secrets.AWS_BEARER_TOKEN_BEDROCK }} | |
| GROK_API_KEY: ${{ secrets.GROK_API_KEY }} | |
| run: | | |
| cd tests/e2e && bash run_responses_state_tests.sh | |
| # ────────────────────────────────────────────── | |
| # E2E: plano tests (multi-Python matrix) | |
| # ────────────────────────────────────────────── | |
| e2e-plano-tests: | |
| needs: docker-build | |
| runs-on: ubuntu-latest-m | |
| strategy: | |
| fail-fast: false | |
| matrix: | |
| python-version: ["3.10", "3.11", "3.12", "3.13", "3.14"] | |
| defaults: | |
| run: | |
| working-directory: ./tests/archgw | |
| steps: | |
| - name: Checkout code | |
| uses: actions/checkout@v6 | |
| - name: Set up Python | |
| uses: actions/setup-python@v6 | |
| with: | |
| python-version: ${{ matrix.python-version }} | |
| - name: Download plano image | |
| uses: actions/download-artifact@v7 | |
| with: | |
| name: plano-image | |
| path: /tmp | |
| - name: Load plano image | |
| run: docker load -i /tmp/plano-image.tar | |
| - name: Start plano | |
| env: | |
| OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }} | |
| MISTRAL_API_KEY: ${{ secrets.MISTRAL_API_KEY }} | |
| GROQ_API_KEY: ${{ secrets.GROQ_API_KEY }} | |
| ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }} | |
| AZURE_API_KEY: ${{ secrets.AZURE_API_KEY }} | |
| AWS_BEARER_TOKEN_BEDROCK: ${{ secrets.AWS_BEARER_TOKEN_BEDROCK }} | |
| run: | | |
| docker compose up | tee &> plano.logs & | |
| - name: Wait for plano to be healthy | |
| run: | | |
| source common.sh && wait_for_healthz http://localhost:10000/healthz | |
| - name: Install uv | |
| run: curl -LsSf https://astral.sh/uv/install.sh | sh | |
| - name: Install test dependencies | |
| run: uv sync | |
| - name: Run plano tests | |
| run: | | |
| uv run pytest || tail -100 plano.logs | |
| - name: Stop plano docker container | |
| env: | |
| OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }} | |
| MISTRAL_API_KEY: ${{ secrets.MISTRAL_API_KEY }} | |
| GROQ_API_KEY: ${{ secrets.GROQ_API_KEY }} | |
| ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }} | |
| run: | | |
| docker compose down | |
| # ────────────────────────────────────────────── | |
| # E2E: demo — preference based routing | |
| # ────────────────────────────────────────────── | |
| e2e-demo-preference: | |
| needs: docker-build | |
| runs-on: ubuntu-latest-m | |
| steps: | |
| - name: Checkout code | |
| uses: actions/checkout@v6 | |
| - name: Set up Python | |
| uses: actions/setup-python@v6 | |
| with: | |
| python-version: "3.14" | |
| - name: Download plano image | |
| uses: actions/download-artifact@v7 | |
| with: | |
| name: plano-image | |
| path: /tmp | |
| - name: Load plano image | |
| run: docker load -i /tmp/plano-image.tar | |
| - name: Install uv | |
| run: curl -LsSf https://astral.sh/uv/install.sh | sh | |
| - name: Setup python venv | |
| run: python -m venv venv | |
| - name: Install hurl | |
| run: | | |
| curl --location --remote-name https://github.com/Orange-OpenSource/hurl/releases/download/4.0.0/hurl_4.0.0_amd64.deb | |
| sudo dpkg -i hurl_4.0.0_amd64.deb | |
| - name: Install plano gateway and test dependencies | |
| run: | | |
| source venv/bin/activate | |
| cd cli && echo "installing plano cli" && uv sync && uv tool install . | |
| cd ../demos/shared/test_runner && echo "installing test dependencies" && uv sync | |
| - name: Run demo tests | |
| env: | |
| OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }} | |
| MISTRAL_API_KEY: ${{ secrets.MISTRAL_API_KEY }} | |
| GROQ_API_KEY: ${{ secrets.GROQ_API_KEY }} | |
| ARCH_API_KEY: ${{ secrets.ARCH_API_KEY }} | |
| ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }} | |
| run: | | |
| source venv/bin/activate | |
| cd demos/shared/test_runner && sh run_demo_tests.sh llm_routing/preference_based_routing | |
| # ────────────────────────────────────────────── | |
| # E2E: demo — currency conversion | |
| # ────────────────────────────────────────────── | |
| e2e-demo-currency: | |
| needs: docker-build | |
| runs-on: ubuntu-latest-m | |
| steps: | |
| - name: Checkout code | |
| uses: actions/checkout@v6 | |
| - name: Set up Python | |
| uses: actions/setup-python@v6 | |
| with: | |
| python-version: "3.14" | |
| - name: Download plano image | |
| uses: actions/download-artifact@v7 | |
| with: | |
| name: plano-image | |
| path: /tmp | |
| - name: Load plano image | |
| run: docker load -i /tmp/plano-image.tar | |
| - name: Install uv | |
| run: curl -LsSf https://astral.sh/uv/install.sh | sh | |
| - name: Setup python venv | |
| run: python -m venv venv | |
| - name: Install hurl | |
| run: | | |
| curl --location --remote-name https://github.com/Orange-OpenSource/hurl/releases/download/4.0.0/hurl_4.0.0_amd64.deb | |
| sudo dpkg -i hurl_4.0.0_amd64.deb | |
| - name: Install plano gateway and test dependencies | |
| run: | | |
| source venv/bin/activate | |
| cd cli && echo "installing plano cli" && uv sync && uv tool install . | |
| cd ../demos/shared/test_runner && echo "installing test dependencies" && uv sync | |
| - name: Run demo tests | |
| env: | |
| OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }} | |
| MISTRAL_API_KEY: ${{ secrets.MISTRAL_API_KEY }} | |
| GROQ_API_KEY: ${{ secrets.GROQ_API_KEY }} | |
| run: | | |
| source venv/bin/activate | |
| cd demos/shared/test_runner && sh run_demo_tests.sh advanced/currency_exchange |