diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml new file mode 100644 index 00000000..3cca8fb0 --- /dev/null +++ b/.github/workflows/ci.yml @@ -0,0 +1,479 @@ +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@v4 + - uses: actions/setup-python@v5 + - 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@v4 + + - name: Set up Python + uses: actions/setup-python@v5 + with: + python-version: "3.12" + + - name: Install uv + run: curl -LsSf https://astral.sh/uv/install.sh | sh + + - name: Install plano tools + run: uv sync --extra dev + + - name: Run tests + run: uv run pytest + + # ────────────────────────────────────────────── + # Single Docker build — shared by all downstream jobs + # ────────────────────────────────────────────── + docker-build: + runs-on: ubuntu-latest + steps: + - name: Checkout code + uses: actions/checkout@v4 + + - 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.6 + ${{ 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.6 ${{ env.DOCKER_IMAGE }}:latest -o /tmp/plano-image.tar + + - name: Upload image artifact + uses: actions/upload-artifact@v4 + with: + name: plano-image + path: /tmp/plano-image.tar + retention-days: 1 + + # ────────────────────────────────────────────── + # Validate plano config + # ────────────────────────────────────────────── + validate-config: + needs: docker-build + runs-on: ubuntu-latest + steps: + - name: Checkout code + uses: actions/checkout@v4 + + - name: Set up Python + uses: actions/setup-python@v5 + with: + python-version: "3.12" + + - name: Download plano image + uses: actions/download-artifact@v4 + with: + name: plano-image + path: /tmp + + - name: Load plano image + run: docker load -i /tmp/plano-image.tar + + - 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@v4 + + - name: Download plano image + uses: actions/download-artifact@v4 + 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@v4 + + - 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@v4 + 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@v5 + with: + python-version: "3.12" + + - name: Install uv + uses: astral-sh/setup-uv@v5 + 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@v4 + + - 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@v4 + 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@v5 + with: + python-version: "3.12" + + - name: Install uv + uses: astral-sh/setup-uv@v5 + 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@v4 + + - 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@v4 + 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@v5 + with: + python-version: "3.12" + + - name: Install uv + uses: astral-sh/setup-uv@v5 + 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@v4 + + - name: Set up Python + uses: actions/setup-python@v5 + with: + python-version: ${{ matrix.python-version }} + + - name: Download plano image + uses: actions/download-artifact@v4 + 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@v4 + + - name: Set up Python + uses: actions/setup-python@v5 + with: + python-version: "3.12" + + - name: Download plano image + uses: actions/download-artifact@v4 + 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 use_cases/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@v4 + + - name: Set up Python + uses: actions/setup-python@v5 + with: + python-version: "3.12" + + - name: Download plano image + uses: actions/download-artifact@v4 + 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 samples_python/currency_exchange diff --git a/.github/workflows/docker-push-main.yml b/.github/workflows/docker-push-main.yml index 224f2682..d62b91d6 100644 --- a/.github/workflows/docker-push-main.yml +++ b/.github/workflows/docker-push-main.yml @@ -2,6 +2,7 @@ name: Publish docker image (latest) env: DOCKER_IMAGE: katanemo/plano + GHCR_IMAGE: ghcr.io/${{ github.repository_owner }}/plano on: push: @@ -10,9 +11,10 @@ on: permissions: contents: read + packages: write jobs: - # Build ARM64 image on native ARM64 runner. + # Build ARM64 image on native ARM64 runner — push to both registries build-arm64: runs-on: [linux-arm64] steps: @@ -25,13 +27,12 @@ jobs: username: ${{ secrets.DOCKER_USERNAME }} password: ${{ secrets.DOCKER_PASSWORD }} - - name: Extract metadata (tags, labels) for Docker - id: meta - uses: docker/metadata-action@v5 + - name: Log in to GHCR + uses: docker/login-action@v3 with: - images: ${{ env.DOCKER_IMAGE }} - tags: | - type=raw,value=latest # Force the tag to be "latest" + registry: ghcr.io + username: ${{ github.actor }} + password: ${{ secrets.GITHUB_TOKEN }} - name: Build and Push ARM64 Image uses: docker/build-push-action@v5 @@ -40,9 +41,11 @@ jobs: file: ./Dockerfile platforms: linux/arm64 push: true - tags: ${{ steps.meta.outputs.tags }}-arm64 + tags: | + ${{ env.DOCKER_IMAGE }}:latest-arm64 + ${{ env.GHCR_IMAGE }}:latest-arm64 - # Build AMD64 image on GitHub's AMD64 runner + # Build AMD64 image on GitHub's AMD64 runner — push to both registries build-amd64: runs-on: ubuntu-latest steps: @@ -55,13 +58,12 @@ jobs: username: ${{ secrets.DOCKER_USERNAME }} password: ${{ secrets.DOCKER_PASSWORD }} - - name: Extract metadata (tags, labels) for Docker - id: meta - uses: docker/metadata-action@v5 + - name: Log in to GHCR + uses: docker/login-action@v3 with: - images: ${{ env.DOCKER_IMAGE }} - tags: | - type=raw,value=latest # Force the tag to be "latest" + registry: ghcr.io + username: ${{ github.actor }} + password: ${{ secrets.GITHUB_TOKEN }} - name: Build and Push AMD64 Image uses: docker/build-push-action@v5 @@ -70,13 +72,14 @@ jobs: file: ./Dockerfile platforms: linux/amd64 push: true - tags: ${{ steps.meta.outputs.tags }}-amd64 + tags: | + ${{ env.DOCKER_IMAGE }}:latest-amd64 + ${{ env.GHCR_IMAGE }}:latest-amd64 - - # Combine ARM64 and AMD64 images into a multi-arch manifest + # Combine ARM64 and AMD64 images into multi-arch manifests for both registries create-manifest: runs-on: ubuntu-latest - needs: [build-arm64, build-amd64] # Wait for both builds + needs: [build-arm64, build-amd64] steps: - name: Log in to Docker Hub uses: docker/login-action@v3 @@ -84,17 +87,23 @@ jobs: username: ${{ secrets.DOCKER_USERNAME }} password: ${{ secrets.DOCKER_PASSWORD }} - - name: Extract metadata (tags, labels) for Docker - id: meta - uses: docker/metadata-action@v5 + - name: Log in to GHCR + uses: docker/login-action@v3 with: - images: ${{ env.DOCKER_IMAGE }} - tags: | - type=raw,value=latest # Force the tag to be "latest" + registry: ghcr.io + username: ${{ github.actor }} + password: ${{ secrets.GITHUB_TOKEN }} - - name: Create Multi-Arch Manifest + - name: Create Docker Hub Multi-Arch Manifest run: | - # Combine the architecture-specific images into a "latest" manifest - docker buildx imagetools create -t ${{ steps.meta.outputs.tags }} \ + docker buildx imagetools create \ + -t ${{ env.DOCKER_IMAGE }}:latest \ ${{ env.DOCKER_IMAGE }}:latest-arm64 \ ${{ env.DOCKER_IMAGE }}:latest-amd64 + + - name: Create GHCR Multi-Arch Manifest + run: | + docker buildx imagetools create \ + -t ${{ env.GHCR_IMAGE }}:latest \ + ${{ env.GHCR_IMAGE }}:latest-arm64 \ + ${{ env.GHCR_IMAGE }}:latest-amd64 diff --git a/.github/workflows/docker-push-release.yml b/.github/workflows/docker-push-release.yml index cdaf1258..a3acbccd 100644 --- a/.github/workflows/docker-push-release.yml +++ b/.github/workflows/docker-push-release.yml @@ -2,6 +2,7 @@ name: Publish docker image (release) env: DOCKER_IMAGE: katanemo/plano + GHCR_IMAGE: ghcr.io/${{ github.repository_owner }}/plano on: release: @@ -9,9 +10,10 @@ on: permissions: contents: read + packages: write jobs: - # Build ARM64 image on native ARM64 runner + # Build ARM64 image on native ARM64 runner — push to both registries build-arm64: runs-on: [linux-arm64] steps: @@ -24,7 +26,14 @@ jobs: username: ${{ secrets.DOCKER_USERNAME }} password: ${{ secrets.DOCKER_PASSWORD }} - - name: Extract metadata (tags, labels) for Docker + - name: Log in to GHCR + uses: docker/login-action@v3 + with: + registry: ghcr.io + username: ${{ github.actor }} + password: ${{ secrets.GITHUB_TOKEN }} + + - name: Extract metadata for Docker id: meta uses: docker/metadata-action@v5 with: @@ -39,9 +48,11 @@ jobs: file: ./Dockerfile platforms: linux/arm64 push: true - tags: ${{ steps.meta.outputs.tags }}-arm64 + tags: | + ${{ steps.meta.outputs.tags }}-arm64 + ${{ env.GHCR_IMAGE }}:${{ github.event.release.tag_name }}-arm64 - # Build AMD64 image on GitHub's AMD64 runner + # Build AMD64 image on GitHub's AMD64 runner — push to both registries build-amd64: runs-on: ubuntu-latest steps: @@ -54,7 +65,14 @@ jobs: username: ${{ secrets.DOCKER_USERNAME }} password: ${{ secrets.DOCKER_PASSWORD }} - - name: Extract metadata (tags, labels) for Docker + - name: Log in to GHCR + uses: docker/login-action@v3 + with: + registry: ghcr.io + username: ${{ github.actor }} + password: ${{ secrets.GITHUB_TOKEN }} + + - name: Extract metadata for Docker id: meta uses: docker/metadata-action@v5 with: @@ -69,12 +87,14 @@ jobs: file: ./Dockerfile platforms: linux/amd64 push: true - tags: ${{ steps.meta.outputs.tags }}-amd64 + tags: | + ${{ steps.meta.outputs.tags }}-amd64 + ${{ env.GHCR_IMAGE }}:${{ github.event.release.tag_name }}-amd64 - # Combine ARM64 and AMD64 images into a multi-arch manifest + # Combine ARM64 and AMD64 images into multi-arch manifests for both registries create-manifest: runs-on: ubuntu-latest - needs: [build-arm64, build-amd64] # Wait for both builds + needs: [build-arm64, build-amd64] steps: - name: Log in to Docker Hub uses: docker/login-action@v3 @@ -82,7 +102,14 @@ jobs: username: ${{ secrets.DOCKER_USERNAME }} password: ${{ secrets.DOCKER_PASSWORD }} - - name: Extract metadata (tags, labels) for Docker + - name: Log in to GHCR + uses: docker/login-action@v3 + with: + registry: ghcr.io + username: ${{ github.actor }} + password: ${{ secrets.GITHUB_TOKEN }} + + - name: Extract metadata for Docker id: meta uses: docker/metadata-action@v5 with: @@ -90,9 +117,17 @@ jobs: tags: | type=raw,value={{tag}} - - name: Create Multi-Arch Manifest + - name: Create Docker Hub Multi-Arch Manifest run: | - # Combine the architecture-specific images into a single manifest - docker buildx imagetools create -t ${{ steps.meta.outputs.tags }} \ + docker buildx imagetools create \ + -t ${{ steps.meta.outputs.tags }} \ ${{ steps.meta.outputs.tags }}-arm64 \ ${{ steps.meta.outputs.tags }}-amd64 + + - name: Create GHCR Multi-Arch Manifest + run: | + TAG=${{ github.event.release.tag_name }} + docker buildx imagetools create \ + -t ${{ env.GHCR_IMAGE }}:${TAG} \ + ${{ env.GHCR_IMAGE }}:${TAG}-arm64 \ + ${{ env.GHCR_IMAGE }}:${TAG}-amd64 diff --git a/.github/workflows/docker-security-scan.yml b/.github/workflows/docker-security-scan.yml deleted file mode 100644 index 03150064..00000000 --- a/.github/workflows/docker-security-scan.yml +++ /dev/null @@ -1,56 +0,0 @@ -name: Docker Security Scan - -env: - DOCKER_IMAGE: katanemo/plano - -on: - push: - branches: - - main - pull_request: - -permissions: - contents: read - security-events: write - -jobs: - scan: - runs-on: ubuntu-latest - steps: - - name: Checkout Repository - uses: actions/checkout@v4 - - - name: Build Docker Image - uses: docker/build-push-action@v5 - with: - context: . - file: ./Dockerfile - platforms: linux/amd64 - push: false - tags: ${{ env.DOCKER_IMAGE }}:scan - - - name: Run Trivy vulnerability scanner - uses: aquasecurity/trivy-action@master - with: - image-ref: ${{ env.DOCKER_IMAGE }}:scan - format: table - # Fail on PRs so vulnerabilities block merge; on main just report - 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 }}:scan - 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 diff --git a/.github/workflows/e2e_plano_tests.yml b/.github/workflows/e2e_plano_tests.yml deleted file mode 100644 index 66e879ba..00000000 --- a/.github/workflows/e2e_plano_tests.yml +++ /dev/null @@ -1,72 +0,0 @@ -name: e2e plano tests - -on: - push: - branches: - - main - pull_request: - -permissions: - contents: read - -jobs: - e2e_plano_tests: - 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@v3 - - - name: Set up Python - uses: actions/setup-python@v4 - with: - python-version: ${{ matrix.python-version }} - cache: "pip" # auto-caches based on requirements files - - - name: build plano docker image - run: | - cd ../../ && docker build -f Dockerfile . -t katanemo/plano -t katanemo/plano:0.4.6 -t katanemo/plano:latest - - - 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 diff --git a/.github/workflows/e2e_test_currency_convert.yml b/.github/workflows/e2e_test_currency_convert.yml deleted file mode 100644 index 9788bc52..00000000 --- a/.github/workflows/e2e_test_currency_convert.yml +++ /dev/null @@ -1,54 +0,0 @@ -name: e2e demo tests currency conversion - -permissions: - contents: read - -on: - push: - branches: - - main - pull_request: - -jobs: - e2e_demo_tests: - runs-on: ubuntu-latest-m - - steps: - - name: Checkout code - uses: actions/checkout@v3 - - - name: Set up Python - uses: actions/setup-python@v4 - with: - python-version: "3.12" - - - name: build plano docker image - run: | - docker build -f Dockerfile . -t katanemo/plano -t katanemo/plano:0.4.6 - - - 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 samples_python/currency_exchange diff --git a/.github/workflows/e2e_test_preference_based_routing.yml b/.github/workflows/e2e_test_preference_based_routing.yml deleted file mode 100644 index 59866592..00000000 --- a/.github/workflows/e2e_test_preference_based_routing.yml +++ /dev/null @@ -1,56 +0,0 @@ -name: e2e demo preference based routing tests - -permissions: - contents: read - -on: - push: - branches: - - main - pull_request: - -jobs: - e2e_demo_tests: - runs-on: ubuntu-latest-m - - steps: - - name: Checkout code - uses: actions/checkout@v3 - - - name: Set up Python - uses: actions/setup-python@v4 - with: - python-version: "3.12" - - - name: build plano docker image - run: | - docker build -f Dockerfile . -t katanemo/plano -t katanemo/plano:0.4.6 - - - 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 use_cases/preference_based_routing diff --git a/.github/workflows/e2e_tests.yml b/.github/workflows/e2e_tests.yml deleted file mode 100644 index 22dcc910..00000000 --- a/.github/workflows/e2e_tests.yml +++ /dev/null @@ -1,203 +0,0 @@ -name: e2e tests - -on: - push: - branches: - - main - pull_request: - -permissions: - contents: read - -# Shared env vars for all jobs that run tests -env: - PLANO_DOCKER_IMAGE: katanemo/plano:e2e - -jobs: - # ────────────────────────────────────────────── - # Job 1: Build the Docker image once, with cache - # ────────────────────────────────────────────── - build: - runs-on: ubuntu-latest - steps: - - name: Checkout code - uses: actions/checkout@v4 - - - 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 }} - cache-from: type=gha - cache-to: type=gha,mode=max - - - name: Save image as artifact - run: docker save ${{ env.PLANO_DOCKER_IMAGE }} -o /tmp/plano-image.tar - - - name: Upload image artifact - uses: actions/upload-artifact@v4 - with: - name: plano-image - path: /tmp/plano-image.tar - retention-days: 1 - - # ────────────────────────────────────────────── - # Job 2a: prompt_gateway tests - # ────────────────────────────────────────────── - test-prompt-gateway: - needs: build - runs-on: ubuntu-latest - steps: - - name: Checkout code - uses: actions/checkout@v4 - - - 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@v4 - 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@v5 - with: - python-version: "3.12" - - - name: Install uv - uses: astral-sh/setup-uv@v5 - 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 - - # ────────────────────────────────────────────── - # Job 2b: model_alias_routing + responses API tests - # ────────────────────────────────────────────── - test-model-alias-routing: - needs: build - runs-on: ubuntu-latest - steps: - - name: Checkout code - uses: actions/checkout@v4 - - - 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@v4 - 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@v5 - with: - python-version: "3.12" - - - name: Install uv - uses: astral-sh/setup-uv@v5 - 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 - - # ────────────────────────────────────────────── - # Job 2c: responses API with state storage tests - # ────────────────────────────────────────────── - test-responses-api-with-state: - needs: build - runs-on: ubuntu-latest - steps: - - name: Checkout code - uses: actions/checkout@v4 - - - 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@v4 - 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@v5 - with: - python-version: "3.12" - - - name: Install uv - uses: astral-sh/setup-uv@v5 - 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 diff --git a/.github/workflows/ghrc-push-main.yml b/.github/workflows/ghrc-push-main.yml deleted file mode 100644 index a029e46f..00000000 --- a/.github/workflows/ghrc-push-main.yml +++ /dev/null @@ -1,88 +0,0 @@ -name: Publish docker image to ghcr (latest) - -env: - IMAGE_NAME: ghcr.io/${{ github.repository_owner }}/plano - -on: - push: - branches: [main] - -jobs: - build-arm64: - runs-on: [linux-arm64] - permissions: { contents: read, packages: write } - steps: - - uses: actions/checkout@v4 - - uses: docker/login-action@v3 - with: - registry: ghcr.io - username: ${{ github.actor }} - password: ${{ secrets.GITHUB_TOKEN }} - - - id: meta - uses: docker/metadata-action@v5 - with: - images: ${{ env.IMAGE_NAME }} - tags: | - type=raw,value=latest - - - name: Build and Push ARM64 Image - uses: docker/build-push-action@v5 - with: - context: . - file: ./Dockerfile - platforms: linux/arm64 - push: true - # produce ghcr.io//plano:latest-arm64 - tags: ${{ steps.meta.outputs.tags }}-arm64 - - build-amd64: - runs-on: ubuntu-latest - permissions: { contents: read, packages: write } - steps: - - uses: actions/checkout@v4 - - uses: docker/login-action@v3 - with: - registry: ghcr.io - username: ${{ github.actor }} - password: ${{ secrets.GITHUB_TOKEN }} - - - id: meta - uses: docker/metadata-action@v5 - with: - images: ${{ env.IMAGE_NAME }} - tags: | - type=raw,value=latest - - - name: Build and Push AMD64 Image - uses: docker/build-push-action@v5 - with: - context: . - file: ./Dockerfile - platforms: linux/amd64 - push: true - tags: ${{ steps.meta.outputs.tags }}-amd64 - - create-manifest: - runs-on: ubuntu-latest - needs: [build-arm64, build-amd64] - permissions: { contents: read, packages: write } - steps: - - uses: docker/login-action@v3 - with: - registry: ghcr.io - username: ${{ github.actor }} - password: ${{ secrets.GITHUB_TOKEN }} - - - id: meta - uses: docker/metadata-action@v5 - with: - images: ${{ env.IMAGE_NAME }} - tags: | - type=raw,value=latest - - - name: Create Multi-Arch Manifest - run: | - docker buildx imagetools create -t ${{ steps.meta.outputs.tags }} \ - ${{ env.IMAGE_NAME }}:latest-arm64 \ - ${{ env.IMAGE_NAME }}:latest-amd64 diff --git a/.github/workflows/ghrc-push-release.yml b/.github/workflows/ghrc-push-release.yml deleted file mode 100644 index 99e693a2..00000000 --- a/.github/workflows/ghrc-push-release.yml +++ /dev/null @@ -1,87 +0,0 @@ -name: release - publish docker image to ghcr (latest) - -env: - IMAGE_NAME: ghcr.io/${{ github.repository_owner }}/plano - -on: - release: - types: [published] - -jobs: - build-arm64: - runs-on: [linux-arm64] - permissions: { contents: read, packages: write } - steps: - - uses: actions/checkout@v4 - - uses: docker/login-action@v3 - with: - registry: ghcr.io - username: ${{ github.actor }} - password: ${{ secrets.GITHUB_TOKEN }} - - - id: meta - uses: docker/metadata-action@v5 - with: - images: ${{ env.IMAGE_NAME }} - tags: | - type=raw,value={{tag}} - - - name: Build and Push ARM64 Image - uses: docker/build-push-action@v5 - with: - context: . - file: ./Dockerfile - platforms: linux/arm64 - push: true - tags: ${{ steps.meta.outputs.tags }}-arm64 - - build-amd64: - runs-on: ubuntu-latest - permissions: { contents: read, packages: write } - steps: - - uses: actions/checkout@v4 - - uses: docker/login-action@v3 - with: - registry: ghcr.io - username: ${{ github.actor }} - password: ${{ secrets.GITHUB_TOKEN }} - - - id: meta - uses: docker/metadata-action@v5 - with: - images: ${{ env.IMAGE_NAME }} - tags: | - type=raw,value={{tag}} - - - name: Build and Push AMD64 Image - uses: docker/build-push-action@v5 - with: - context: . - file: ./Dockerfile - platforms: linux/amd64 - push: true - tags: ${{ steps.meta.outputs.tags }}-amd64 - - create-manifest: - runs-on: ubuntu-latest - needs: [build-arm64, build-amd64] - permissions: { contents: read, packages: write } - steps: - - uses: docker/login-action@v3 - with: - registry: ghcr.io - username: ${{ github.actor }} - password: ${{ secrets.GITHUB_TOKEN }} - - - id: meta - uses: docker/metadata-action@v5 - with: - images: ${{ env.IMAGE_NAME }} - tags: | - type=raw,value={{tag}} - - - name: Create Multi-Arch Manifest - run: | - docker buildx imagetools create -t ${{ steps.meta.outputs.tags }} \ - ${{ steps.meta.outputs.tags }}-arm64 \ - ${{ steps.meta.outputs.tags }}-amd64 diff --git a/.github/workflows/plano_tools_tests.yml b/.github/workflows/plano_tools_tests.yml deleted file mode 100644 index 57f01048..00000000 --- a/.github/workflows/plano_tools_tests.yml +++ /dev/null @@ -1,37 +0,0 @@ -name: plano tools tests - -permissions: - contents: read - -on: - push: - branches: - - main - pull_request: - -jobs: - plano_tools_tests: - runs-on: ubuntu-latest-m - defaults: - run: - working-directory: ./cli - - steps: - - name: Checkout code - uses: actions/checkout@v3 - - - name: Set up Python - uses: actions/setup-python@v4 - with: - python-version: "3.12" - - - name: install uv - run: curl -LsSf https://astral.sh/uv/install.sh | sh - - - name: install plano tools - run: | - uv sync --extra dev - - - name: run tests - run: | - uv run pytest diff --git a/.github/workflows/pre-commit.yml b/.github/workflows/pre-commit.yml deleted file mode 100644 index b3754b72..00000000 --- a/.github/workflows/pre-commit.yml +++ /dev/null @@ -1,17 +0,0 @@ -name: pre-commit - -on: - pull_request: - push: - branches: [main] - -permissions: - contents: read - -jobs: - pre-commit: - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v3 - - uses: actions/setup-python@v3 - - uses: pre-commit/action@v3.0.1 diff --git a/.github/workflows/rust_tests.yml b/.github/workflows/rust_tests.yml deleted file mode 100644 index 5b1867e5..00000000 --- a/.github/workflows/rust_tests.yml +++ /dev/null @@ -1,34 +0,0 @@ -name: rust tests (prompt and llm gateway) - -on: - pull_request: - push: - branches: [main] - -permissions: - contents: read - -jobs: - test: - name: Test - runs-on: ubuntu-latest - defaults: - run: - working-directory: ./crates - - steps: - - name: Setup | Checkout - uses: actions/checkout@v4 - - - name: Setup | Rust - run: rustup toolchain install 1.92 --profile minimal - - - name: Setup | Install wasm toolchain - run: rustup target add wasm32-wasip1 - - - name: Build wasm module - run: | - cargo build --release --target=wasm32-wasip1 -p llm_gateway -p prompt_gateway - - - name: Run unit tests - run: cargo test --lib diff --git a/.github/workflows/validate_plano_config.yml b/.github/workflows/validate_plano_config.yml deleted file mode 100644 index 9d20c98a..00000000 --- a/.github/workflows/validate_plano_config.yml +++ /dev/null @@ -1,34 +0,0 @@ -name: plano config tests - -on: - push: - branches: - - main - pull_request: - -permissions: - contents: read - -jobs: - validate_plano_config: - runs-on: ubuntu-latest - defaults: - run: - working-directory: . - - steps: - - name: Checkout code - uses: actions/checkout@v3 - - - name: Set up Python - uses: actions/setup-python@v4 - with: - python-version: "3.12" - - - name: build plano docker image - run: | - docker build -f Dockerfile . -t katanemo/plano -t katanemo/plano:0.4.6 - - - name: validate plano config - run: | - bash config/validate_plano_config.sh