litellm-rs 0.6.0

A high-performance AI Gateway written in Rust, providing OpenAI-compatible APIs with intelligent routing, load balancing, and enterprise features
Documentation
name: Docker

on:
  workflow_dispatch:

concurrency:
  group: docker-${{ github.ref }}
  cancel-in-progress: true

env:
  REGISTRY: ghcr.io
  IMAGE_NAME: ${{ github.repository }}

jobs:
  # Build and test Docker image
  build-test:
    name: Build and Test Docker Image
    if: github.event_name == 'pull_request' || github.ref == 'refs/heads/develop'
    runs-on: ubuntu-latest
    permissions:
      contents: read
      packages: write
    steps:
    - name: Checkout code
      uses: actions/checkout@v4

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

    - name: Login to Container Registry
      if: github.event_name != 'pull_request'
      uses: docker/login-action@v3
      with:
        registry: ${{ env.REGISTRY }}
        username: ${{ github.actor }}
        password: ${{ secrets.GITHUB_TOKEN }}

    - name: Extract metadata
      id: meta
      uses: docker/metadata-action@v5
      with:
        images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}
        tags: |
          type=ref,event=branch
          type=ref,event=pr
          type=sha,prefix=sha-
          type=raw,value=latest,enable={{is_default_branch}}

    - name: Build Docker image
      uses: docker/build-push-action@v5
      with:
        context: .
        file: ./deployment/docker/Dockerfile
        platforms: linux/amd64
        push: ${{ github.event_name != 'pull_request' }}
        load: ${{ github.event_name == 'pull_request' }}
        tags: ${{ steps.meta.outputs.tags }}
        labels: ${{ steps.meta.outputs.labels }}
        cache-from: type=gha
        cache-to: type=gha,mode=max
        build-args: |
          BUILDTIME=${{ fromJSON(steps.meta.outputs.json).labels['org.opencontainers.image.created'] }}
          VERSION=${{ fromJSON(steps.meta.outputs.json).labels['org.opencontainers.image.version'] }}
          REVISION=${{ fromJSON(steps.meta.outputs.json).labels['org.opencontainers.image.revision'] }}

    - name: Test Docker image
      run: |
        docker run --rm ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:${{ steps.meta.outputs.version }} /bin/sh -lc 'test -x /usr/local/bin/gateway && ldd /usr/local/bin/gateway >/dev/null'

  # Security scan
  security-scan:
    name: Security Scan
    runs-on: ubuntu-latest
    needs: merge-manifests
    if: github.event_name == 'push' && github.ref == 'refs/heads/main'
    permissions:
      contents: read
      packages: read
      security-events: write
    steps:
    - name: Run Trivy vulnerability scanner
      uses: aquasecurity/trivy-action@master
      with:
        image-ref: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:main
        format: 'sarif'
        output: 'trivy-results.sarif'

    - name: Upload Trivy scan results to GitHub Security tab
      uses: github/codeql-action/upload-sarif@v2
      with:
        sarif_file: 'trivy-results.sarif'

  # Multi-architecture build for releases
  multi-arch-build:
    name: Multi-Architecture Build
    runs-on: ubuntu-latest
    if: github.ref == 'refs/heads/main'
    permissions:
      contents: read
      packages: write
    strategy:
      matrix:
        platform:
          - linux/amd64
          - linux/arm64
          - linux/arm/v7
    steps:
    - name: Checkout code
      uses: actions/checkout@v4

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

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

    - name: Login to Container Registry
      uses: docker/login-action@v3
      with:
        registry: ${{ env.REGISTRY }}
        username: ${{ github.actor }}
        password: ${{ secrets.GITHUB_TOKEN }}

    - name: Build and push by digest
      id: build
      uses: docker/build-push-action@v5
      with:
        context: .
        file: ./deployment/docker/Dockerfile
        platforms: ${{ matrix.platform }}
        labels: |
          org.opencontainers.image.title=Rust LiteLLM Gateway
          org.opencontainers.image.description=A high-performance AI Gateway written in Rust
          org.opencontainers.image.version=${{ github.sha }}
          org.opencontainers.image.revision=${{ github.sha }}
          org.opencontainers.image.created=${{ github.event.head_commit.timestamp }}
        outputs: type=image,name=${{ env.REGISTRY }}/${{ env.IMAGE_NAME }},push-by-digest=true,name-canonical=true,push=true
        cache-from: type=gha
        cache-to: type=gha,mode=max

    - name: Export digest
      run: |
        mkdir -p /tmp/digests
        digest="${{ steps.build.outputs.digest }}"
        touch "/tmp/digests/${digest#sha256:}"

    - name: Upload digest
      uses: actions/upload-artifact@v4
      with:
        name: digests
        path: /tmp/digests/*
        if-no-files-found: error
        retention-days: 1

  # Merge multi-architecture manifests
  merge-manifests:
    name: Merge Multi-Architecture Manifests
    runs-on: ubuntu-latest
    if: github.ref == 'refs/heads/main'
    needs: multi-arch-build
    permissions:
      contents: read
      packages: write
    steps:
    - name: Download digests
      uses: actions/download-artifact@v4
      with:
        name: digests
        path: /tmp/digests

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

    - name: Login to Container Registry
      uses: docker/login-action@v3
      with:
        registry: ${{ env.REGISTRY }}
        username: ${{ github.actor }}
        password: ${{ secrets.GITHUB_TOKEN }}

    - name: Create manifest list and push
      working-directory: /tmp/digests
      run: |
        docker buildx imagetools create \
          --tag ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:main \
          --tag ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:latest \
          $(printf '${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}@sha256:%s ' *)

    - name: Inspect image
      run: |
        docker buildx imagetools inspect ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:latest

  # Clean up old images
  cleanup:
    name: Cleanup Old Images
    runs-on: ubuntu-latest
    if: github.ref == 'refs/heads/main'
    needs: merge-manifests
    permissions:
      contents: read
      packages: write
    steps:
    - name: Delete old images
      uses: actions/delete-package-versions@v4
      with:
        package-name: ${{ github.event.repository.name }}
        package-type: container
        min-versions-to-keep: 10
        delete-only-untagged-versions: true