Skip to content

feat(web): merge DigitalOcean release announcement updates #314

feat(web): merge DigitalOcean release announcement updates

feat(web): merge DigitalOcean release announcement updates #314

Workflow file for this run

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