# this workflow is triggered by an API call when there is a new PyPI release of LiteLLM
name: Build, Publish LiteLLM Docker Image. New Release
on:
  workflow_dispatch:
    inputs:
      tag:
        description: "The tag version you want to build"
        required: true
      release_type:
        description: "The release type you want to build. Can be 'latest', 'stable', 'dev', 'rc'"
        type: string
        default: "latest"
      commit_hash:
        description: "Commit hash"
        required: true

# Defines two custom environment variables for the workflow. Used for the Container registry domain, and a name for the Docker image that this workflow builds.
env:
  REGISTRY: ghcr.io
  IMAGE_NAME: ${{ github.repository }}
  CHART_NAME: litellm-helm

# There is a single job in this workflow. It's configured to run on the latest available version of Ubuntu.
jobs:
  # print commit hash, tag, and release type
  print:
    runs-on: ubuntu-latest
    steps:
      - run: |
          echo "Commit hash: ${{ github.event.inputs.commit_hash }}"
          echo "Tag: ${{ github.event.inputs.tag }}"
          echo "Release type: ${{ github.event.inputs.release_type }}"
  docker-hub-deploy:
    if: github.repository == 'BerriAI/litellm'
    runs-on: ubuntu-latest
    steps:
      -
        name: Checkout
        uses: actions/checkout@v4
        with:
          ref: ${{ github.event.inputs.commit_hash }}
      -
        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:
          username: ${{ secrets.DOCKERHUB_USERNAME }}
          password: ${{ secrets.DOCKERHUB_TOKEN }}
      -
        name: Build and push
        uses: docker/build-push-action@v5
        with:
          context: .
          push: true
          tags: litellm/litellm:${{ github.event.inputs.tag || 'latest' }} 
      -
        name: Build and push litellm-database image
        uses: docker/build-push-action@v5
        with:
          context: .
          push: true
          file: ./docker/Dockerfile.database
          tags: litellm/litellm-database:${{ github.event.inputs.tag || 'latest' }}
      -
        name: Build and push litellm-spend-logs image
        uses: docker/build-push-action@v5
        with:
          context: .
          push: true
          file: ./litellm-js/spend-logs/Dockerfile
          tags: litellm/litellm-spend_logs:${{ github.event.inputs.tag || 'latest' }}
      -
        name: Build and push litellm-non_root image
        uses: docker/build-push-action@v5
        with:
          context: .
          push: true
          file: ./docker/Dockerfile.non_root
          tags: litellm/litellm-non_root:${{ github.event.inputs.tag || 'latest' }}
  build-and-push-image:
    runs-on: ubuntu-latest
    # Sets the permissions granted to the `GITHUB_TOKEN` for the actions in this job.
    permissions:
      contents: read
      packages: write
    steps:
      - name: Checkout repository
        uses: actions/checkout@v4
        with:
          ref: ${{ github.event.inputs.commit_hash }}
      # Uses the `docker/login-action` action to log in to the Container registry registry using the account and password that will publish the packages. Once published, the packages are scoped to the account defined here.
      - name: Log in to the Container registry
        uses: docker/login-action@65b78e6e13532edd9afa3aa52ac7964289d1a9c1
        with:
          registry: ${{ env.REGISTRY }}
          username: ${{ github.actor }}
          password: ${{ secrets.GITHUB_TOKEN }}
      # This step uses [docker/metadata-action](https://github.com/docker/metadata-action#about) to extract tags and labels that will be applied to the specified image. The `id` "meta" allows the output of this step to be referenced in a subsequent step. The `images` value provides the base name for the tags and labels.
      - name: Extract metadata (tags, labels) for Docker
        id: meta
        uses: docker/metadata-action@9ec57ed1fcdbf14dcef7dfbe97b2010124a938b7
        with:
          images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}
      # Configure multi platform Docker builds
      - name: Set up QEMU
        uses: docker/setup-qemu-action@e0e4588fad221d38ee467c0bffd91115366dc0c5
      - name: Set up Docker Buildx
        uses: docker/setup-buildx-action@edfb0fe6204400c56fbfd3feba3fe9ad1adfa345
      # This step uses the `docker/build-push-action` action to build the image, based on your repository's `Dockerfile`. If the build succeeds, it pushes the image to GitHub Packages.
      # It uses the `context` parameter to define the build's context as the set of files located in the specified path. For more information, see "[Usage](https://github.com/docker/build-push-action#usage)" in the README of the `docker/build-push-action` repository.
      # It uses the `tags` and `labels` parameters to tag and label the image with the output from the "meta" step.
      - name: Build and push Docker image
        uses: docker/build-push-action@4976231911ebf5f32aad765192d35f942aa48cb8
        with:
          context: .
          push: true
          tags: |
            ${{ steps.meta.outputs.tags }}-${{ github.event.inputs.tag || 'latest' }},
            ${{ steps.meta.outputs.tags }}-${{ github.event.inputs.release_type }}
            ${{ (github.event.inputs.release_type == 'stable'  || github.event.inputs.release_type == 'rc') && format('{0}/berriai/litellm:main-{1}', env.REGISTRY, github.event.inputs.tag) || '' }},
            ${{ github.event.inputs.release_type == 'stable' && format('{0}/berriai/litellm:main-stable', env.REGISTRY) || '' }},
            ${{ (github.event.inputs.release_type == 'stable'  || github.event.inputs.release_type == 'rc') && format('{0}/berriai/litellm:{1}', env.REGISTRY, github.event.inputs.tag) || '' }},
          labels: ${{ steps.meta.outputs.labels }}
          platforms: local,linux/amd64,linux/arm64,linux/arm64/v8
  
  build-and-push-image-ee:
    runs-on: ubuntu-latest
    permissions:
      contents: read
      packages: write
    steps:
      - name: Checkout repository
        uses: actions/checkout@v4
        with:
          ref: ${{ github.event.inputs.commit_hash }}

      - name: Log in to the Container registry
        uses: docker/login-action@65b78e6e13532edd9afa3aa52ac7964289d1a9c1
        with:
          registry: ${{ env.REGISTRY }}
          username: ${{ github.actor }}
          password: ${{ secrets.GITHUB_TOKEN }}

      - name: Extract metadata (tags, labels) for EE Dockerfile
        id: meta-ee
        uses: docker/metadata-action@9ec57ed1fcdbf14dcef7dfbe97b2010124a938b7
        with:
          images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}-ee
      # Configure multi platform Docker builds
      - name: Set up QEMU
        uses: docker/setup-qemu-action@e0e4588fad221d38ee467c0bffd91115366dc0c5
      - name: Set up Docker Buildx
        uses: docker/setup-buildx-action@edfb0fe6204400c56fbfd3feba3fe9ad1adfa345

      - name: Build and push EE Docker image
        uses: docker/build-push-action@f2a1d5e99d037542a71f64918e516c093c6f3fc4
        with:
          context: .
          file: Dockerfile
          push: true
          tags: |
            ${{ steps.meta-ee.outputs.tags }}-${{ github.event.inputs.tag || 'latest' }},
            ${{ steps.meta-ee.outputs.tags }}-${{ github.event.inputs.release_type }}
            ${{ (github.event.inputs.release_type == 'stable'  || github.event.inputs.release_type == 'rc') && format('{0}/berriai/litellm-ee:main-{1}', env.REGISTRY, github.event.inputs.tag) || '' }},
            ${{ github.event.inputs.release_type == 'stable' && format('{0}/berriai/litellm-ee:main-stable', env.REGISTRY) || '' }}
          labels: ${{ steps.meta-ee.outputs.labels }}
          platforms: local,linux/amd64,linux/arm64,linux/arm64/v8
   
  build-and-push-image-database:
    runs-on: ubuntu-latest
    permissions:
      contents: read
      packages: write
    steps:
      - name: Checkout repository
        uses: actions/checkout@v4
        with:
          ref: ${{ github.event.inputs.commit_hash }}

      - name: Log in to the Container registry
        uses: docker/login-action@65b78e6e13532edd9afa3aa52ac7964289d1a9c1
        with:
          registry: ${{ env.REGISTRY }}
          username: ${{ github.actor }}
          password: ${{ secrets.GITHUB_TOKEN }}

      - name: Extract metadata (tags, labels) for database Dockerfile
        id: meta-database
        uses: docker/metadata-action@9ec57ed1fcdbf14dcef7dfbe97b2010124a938b7
        with:
          images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}-database
      # Configure multi platform Docker builds
      - name: Set up QEMU
        uses: docker/setup-qemu-action@e0e4588fad221d38ee467c0bffd91115366dc0c5
      - name: Set up Docker Buildx
        uses: docker/setup-buildx-action@edfb0fe6204400c56fbfd3feba3fe9ad1adfa345

      - name: Build and push Database Docker image
        uses: docker/build-push-action@f2a1d5e99d037542a71f64918e516c093c6f3fc4
        with:
          context: .
          file: ./docker/Dockerfile.database
          push: true
          tags: |
            ${{ steps.meta-database.outputs.tags }}-${{ github.event.inputs.tag || 'latest' }},
            ${{ steps.meta-database.outputs.tags }}-${{ github.event.inputs.release_type }}
            ${{ (github.event.inputs.release_type == 'stable'  || github.event.inputs.release_type == 'rc') && format('{0}/berriai/litellm-database:main-{1}', env.REGISTRY, github.event.inputs.tag) || '' }},
            ${{ github.event.inputs.release_type == 'stable' && format('{0}/berriai/litellm-database:main-stable', env.REGISTRY) || '' }}
          labels: ${{ steps.meta-database.outputs.labels }}
          platforms: local,linux/amd64,linux/arm64,linux/arm64/v8
            
  build-and-push-image-non_root:
    runs-on: ubuntu-latest
    permissions:
      contents: read
      packages: write
    steps:
      - name: Checkout repository
        uses: actions/checkout@v4
        with:
          ref: ${{ github.event.inputs.commit_hash }}

      - name: Log in to the Container registry
        uses: docker/login-action@65b78e6e13532edd9afa3aa52ac7964289d1a9c1
        with:
          registry: ${{ env.REGISTRY }}
          username: ${{ github.actor }}
          password: ${{ secrets.GITHUB_TOKEN }}

      - name: Extract metadata (tags, labels) for non_root Dockerfile
        id: meta-non_root
        uses: docker/metadata-action@9ec57ed1fcdbf14dcef7dfbe97b2010124a938b7
        with:
          images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}-non_root
      # Configure multi platform Docker builds
      - name: Set up QEMU
        uses: docker/setup-qemu-action@e0e4588fad221d38ee467c0bffd91115366dc0c5
      - name: Set up Docker Buildx
        uses: docker/setup-buildx-action@edfb0fe6204400c56fbfd3feba3fe9ad1adfa345

      - name: Build and push non_root Docker image
        uses: docker/build-push-action@f2a1d5e99d037542a71f64918e516c093c6f3fc4
        with:
          context: .
          file: ./docker/Dockerfile.non_root
          push: true
          tags: |
            ${{ steps.meta-non_root.outputs.tags }}-${{ github.event.inputs.tag || 'latest' }},
            ${{ steps.meta-non_root.outputs.tags }}-${{ github.event.inputs.release_type }}
            ${{ (github.event.inputs.release_type == 'stable'  || github.event.inputs.release_type == 'rc') && format('{0}/berriai/litellm-non_root:main-{1}', env.REGISTRY, github.event.inputs.tag) || '' }},
            ${{ github.event.inputs.release_type == 'stable' && format('{0}/berriai/litellm-non_root:main-stable', env.REGISTRY) || '' }}
          labels: ${{ steps.meta-non_root.outputs.labels }} 
          platforms: local,linux/amd64,linux/arm64,linux/arm64/v8
  
  build-and-push-image-spend-logs:
    runs-on: ubuntu-latest
    permissions:
      contents: read
      packages: write
    steps:
      - name: Checkout repository
        uses: actions/checkout@v4
        with:
          ref: ${{ github.event.inputs.commit_hash }}

      - name: Log in to the Container registry
        uses: docker/login-action@65b78e6e13532edd9afa3aa52ac7964289d1a9c1
        with:
          registry: ${{ env.REGISTRY }}
          username: ${{ github.actor }}
          password: ${{ secrets.GITHUB_TOKEN }}

      - name: Extract metadata (tags, labels) for spend-logs Dockerfile
        id: meta-spend-logs
        uses: docker/metadata-action@9ec57ed1fcdbf14dcef7dfbe97b2010124a938b7
        with:
          images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}-spend_logs
      # Configure multi platform Docker builds
      - name: Set up QEMU
        uses: docker/setup-qemu-action@e0e4588fad221d38ee467c0bffd91115366dc0c5
      - name: Set up Docker Buildx
        uses: docker/setup-buildx-action@edfb0fe6204400c56fbfd3feba3fe9ad1adfa345

      - name: Build and push Database Docker image
        uses: docker/build-push-action@f2a1d5e99d037542a71f64918e516c093c6f3fc4
        with:
          context: .
          file: ./litellm-js/spend-logs/Dockerfile
          push: true
          tags: |
            ${{ steps.meta-spend-logs.outputs.tags }}-${{ github.event.inputs.tag || 'latest' }},
            ${{ steps.meta-spend-logs.outputs.tags }}-${{ github.event.inputs.release_type }}
            ${{ (github.event.inputs.release_type == 'stable'  || github.event.inputs.release_type == 'rc') && format('{0}/berriai/litellm-spend_logs:main-{1}', env.REGISTRY, github.event.inputs.tag) || '' }},
            ${{ github.event.inputs.release_type == 'stable' && format('{0}/berriai/litellm-spend_logs:main-stable', env.REGISTRY) || '' }}
          platforms: local,linux/amd64,linux/arm64,linux/arm64/v8

  run-observatory-tests:
    if: github.event.inputs.release_type == 'rc' || github.event.inputs.release_type == 'stable'
    needs: [docker-hub-deploy]
    uses: ./.github/workflows/run_observatory_tests.yml
    with:
      tag: ${{ github.event.inputs.tag }}
      commit_hash: ${{ github.event.inputs.commit_hash }}
    secrets: inherit

  build-and-push-helm-chart:
    if: github.event.inputs.release_type  != 'dev'
    needs: [docker-hub-deploy, build-and-push-image, build-and-push-image-database]
    runs-on: ubuntu-latest
    steps:
      - name: Checkout repository
        uses: actions/checkout@v4
        with:
          fetch-depth: 0

      - name: Log in to the Container registry
        uses: docker/login-action@65b78e6e13532edd9afa3aa52ac7964289d1a9c1
        with:
          registry: ${{ env.REGISTRY }}
          username: ${{ github.actor }}
          password: ${{ secrets.GITHUB_TOKEN }}

      - name: lowercase github.repository_owner
        run: |
          echo "REPO_OWNER=`echo ${{github.repository_owner}} | tr '[:upper:]' '[:lower:]'`" >>${GITHUB_ENV}
    
      # Sync Helm chart version with LiteLLM release version (1-1 versioning)
      # This allows users to easily map Helm chart versions to LiteLLM versions
      # See: https://codefresh.io/docs/docs/ci-cd-guides/helm-best-practices/
      - name: Calculate chart and app versions
        id: chart_version
        shell: bash
        run: |
          INPUT_TAG="${{ github.event.inputs.tag }}"
          RELEASE_TYPE="${{ github.event.inputs.release_type }}"

          # Chart version = LiteLLM version without 'v' prefix (Helm semver convention)
          # v1.81.0 -> 1.81.0, v1.81.0.rc.1 -> 1.81.0.rc.1
          CHART_VERSION="${INPUT_TAG#v}"

          # Add suffix for 'latest' releases (rc already has suffix in tag)
          if [ "$RELEASE_TYPE" = "latest" ]; then
            CHART_VERSION="${CHART_VERSION}-latest"
          fi

          # App version = Docker tag (keeps 'v' prefix to match Docker image tags)
          APP_VERSION="${INPUT_TAG}"

          echo "version=${CHART_VERSION}" | tee -a $GITHUB_OUTPUT
          echo "app_version=${APP_VERSION}" | tee -a $GITHUB_OUTPUT

      - uses: ./.github/actions/helm-oci-chart-releaser
        with:
          name: ${{ env.CHART_NAME }}
          repository: ${{ env.REPO_OWNER }}
          tag: ${{ steps.chart_version.outputs.version }}
          app_version: ${{ steps.chart_version.outputs.app_version }}
          path: deploy/charts/${{ env.CHART_NAME }}
          registry: ${{ env.REGISTRY }}
          registry_username: ${{ github.actor }}
          registry_password: ${{ secrets.GITHUB_TOKEN }}
          update_dependencies: true

  release:
    name: "New LiteLLM Release"
    needs: [docker-hub-deploy, build-and-push-image, build-and-push-image-database]

    runs-on: "ubuntu-latest"
   
    steps:
      - name: Display version
        run: echo "Current version is ${{ github.event.inputs.tag }}"
      - name: "Set Release Tag"
        run: echo "RELEASE_TAG=${{ github.event.inputs.tag }}" >> $GITHUB_ENV
      - name: Display release tag
        run: echo "RELEASE_TAG is $RELEASE_TAG"
      - name: "Create release"
        uses: "actions/github-script@v6"
        with:
          github-token: "${{ secrets.GITHUB_TOKEN }}"
          script: |
            const commitHash = "${{ github.event.inputs.commit_hash}}";
            console.log("Commit Hash:", commitHash); // Add this line for debugging
            try {
              const response = await github.rest.repos.createRelease({
                draft: false,
                generate_release_notes: true,
                target_commitish: commitHash,
                name: process.env.RELEASE_TAG,
                owner: context.repo.owner,
                prerelease: false,
                repo: context.repo.repo,
                tag_name: process.env.RELEASE_TAG,
              });
      
              core.exportVariable('RELEASE_ID', response.data.id);
              core.exportVariable('RELEASE_UPLOAD_URL', response.data.upload_url);
            } catch (error) {
              core.setFailed(error.message);
            }
      - name: Fetch Release Notes
        id: release-notes
        uses: actions/github-script@v6
        with:
          github-token: "${{ secrets.GITHUB_TOKEN }}"
          script: |
            try {
              const response = await github.rest.repos.getRelease({
                owner: context.repo.owner,
                repo: context.repo.repo,
                release_id: process.env.RELEASE_ID,
              });
              const formattedBody = JSON.stringify(response.data.body).slice(1, -1);
              return formattedBody;
            } catch (error) {
              core.setFailed(error.message);
            }
        env:
          RELEASE_ID: ${{ env.RELEASE_ID }}
      - name: Github Releases To Discord
        env:
          WEBHOOK_URL: ${{ secrets.WEBHOOK_URL }}
          REALEASE_TAG: ${{ env.RELEASE_TAG }}
          RELEASE_NOTES: ${{ steps.release-notes.outputs.result }}
        run: |
          curl -H "Content-Type: application/json" -X POST -d '{
            "content": "New LiteLLM release '"${RELEASE_TAG}"'",
            "username": "Release Changelog",
            "avatar_url": "https://cdn.discordapp.com/avatars/487431320314576937/bd64361e4ba6313d561d54e78c9e7171.png",
            "embeds": [
              {
                "title": "Changelog for LiteLLM '"${RELEASE_TAG}"'",
                "description": "'"${RELEASE_NOTES}"'",
                "color": 2105893
              }
            ]
          }' $WEBHOOK_URL

