---
name: 'build container images (reusable)'

on:
  workflow_call:
    inputs:
      base-image:
        description: 'Base image'
        required: true
        type: string
      grpc-base-image:
        description: 'GRPC Base image, must be a compatible image with base-image'
        required: false
        default: ''
        type: string
      build-type:
        description: 'Build type'
        default: ''
        type: string
      cuda-major-version:
        description: 'CUDA major version'
        default: "11"
        type: string
      cuda-minor-version:
        description: 'CUDA minor version'
        default: "7"
        type: string
      platforms:
        description: 'Platforms'
        default: ''
        type: string
      tag-latest:
        description: 'Tag latest'
        default: ''
        type: string
      latest-image:
          description: 'Tag latest'
          default: ''
          type: string
      latest-image-aio:
          description: 'Tag latest'
          default: ''
          type: string
      tag-suffix:
        description: 'Tag suffix'
        default: ''
        type: string
      ffmpeg:
        description: 'FFMPEG'
        default: ''
        type: string
      image-type:
        description: 'Image type'
        default: ''
        type: string
      runs-on:
        description: 'Runs on'
        required: true
        default: ''
        type: string
      makeflags:
        description: 'Make Flags'
        required: false
        default: '--jobs=4 --output-sync=target'
        type: string
      aio:
        description: 'AIO Image Name'
        required: false
        default: ''
        type: string
    secrets:
      dockerUsername:
        required: true
      dockerPassword:
        required: true
      quayUsername:
        required: true
      quayPassword:
        required: true
jobs:
  reusable_image-build:
    runs-on: ${{ inputs.runs-on }}
    steps:
      - name: Force Install GIT latest
        run: |
          sudo apt-get update \
          && sudo apt-get install -y software-properties-common \
          && sudo apt-get update \
          && sudo add-apt-repository -y ppa:git-core/ppa \
          && sudo apt-get update \
          && sudo apt-get install -y git
      - name: Checkout
        uses: actions/checkout@v4

      - name: Release space from worker
        if: inputs.runs-on == 'ubuntu-latest'
        run: |
          echo "Listing top largest packages"
          pkgs=$(dpkg-query -Wf '${Installed-Size}\t${Package}\t${Status}\n' | awk '$NF == "installed"{print $1 "\t" $2}' | sort -nr)
          head -n 30 <<< "${pkgs}"
          echo
          df -h
          echo
          sudo apt-get remove -y '^llvm-.*|^libllvm.*' || true
          sudo apt-get remove --auto-remove android-sdk-platform-tools || true
          sudo apt-get purge --auto-remove android-sdk-platform-tools || true
          sudo rm -rf /usr/local/lib/android
          sudo apt-get remove -y '^dotnet-.*|^aspnetcore-.*' || true
          sudo rm -rf /usr/share/dotnet
          sudo apt-get remove -y '^mono-.*' || true
          sudo apt-get remove -y '^ghc-.*' || true
          sudo apt-get remove -y '.*jdk.*|.*jre.*' || true
          sudo apt-get remove -y 'php.*' || true
          sudo apt-get remove -y hhvm powershell firefox monodoc-manual msbuild || true
          sudo apt-get remove -y '^google-.*' || true
          sudo apt-get remove -y azure-cli || true
          sudo apt-get remove -y '^mongo.*-.*|^postgresql-.*|^mysql-.*|^mssql-.*' || true
          sudo apt-get remove -y '^gfortran-.*' || true
          sudo apt-get remove -y microsoft-edge-stable || true
          sudo apt-get remove -y firefox || true
          sudo apt-get remove -y powershell || true
          sudo apt-get remove -y r-base-core || true
          sudo apt-get autoremove -y
          sudo apt-get clean
          echo
          echo "Listing top largest packages"
          pkgs=$(dpkg-query -Wf '${Installed-Size}\t${Package}\t${Status}\n' | awk '$NF == "installed"{print $1 "\t" $2}' | sort -nr)
          head -n 30 <<< "${pkgs}"
          echo
          sudo rm -rfv build || true
          sudo rm -rf /usr/share/dotnet || true
          sudo rm -rf /opt/ghc || true
          sudo rm -rf "/usr/local/share/boost" || true
          sudo rm -rf "$AGENT_TOOLSDIRECTORY" || true
          df -h

      - name: Docker meta
        id: meta
        uses: docker/metadata-action@v5
        with:
          images: |
            quay.io/go-skynet/local-ai
            localai/localai
          tags: |
            type=ref,event=branch
            type=semver,pattern={{raw}}
            type=sha
          flavor: |
            latest=${{ inputs.tag-latest }}
            suffix=${{ inputs.tag-suffix }}

      - name: Docker meta AIO (quay.io)
        if: inputs.aio != ''
        id: meta_aio
        uses: docker/metadata-action@v5
        with:
          images: |
            quay.io/go-skynet/local-ai
          tags: |
            type=ref,event=branch
            type=semver,pattern={{raw}}
          flavor: |
            latest=${{ inputs.tag-latest }}
            suffix=${{ inputs.aio }}

      - name: Docker meta AIO (dockerhub)
        if: inputs.aio != ''
        id: meta_aio_dockerhub
        uses: docker/metadata-action@v5
        with:
          images: |
            localai/localai
          tags: |
            type=ref,event=branch
            type=semver,pattern={{raw}}
          flavor: |
            latest=${{ inputs.tag-latest }}
            suffix=${{ inputs.aio }}

      - name: Set up QEMU
        uses: docker/setup-qemu-action@master
        with:
          platforms: all

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

      - name: Login to DockerHub
        if: github.event_name != 'pull_request'
        uses: docker/login-action@v3
        with:
          username: ${{ secrets.dockerUsername }}
          password: ${{ secrets.dockerPassword }}

      - name: Login to DockerHub
        if: github.event_name != 'pull_request'
        uses: docker/login-action@v3
        with:
          registry: quay.io
          username: ${{ secrets.quayUsername }}
          password: ${{ secrets.quayPassword }}

      - name: Build and push
        uses: docker/build-push-action@v5
        with:
          builder: ${{ steps.buildx.outputs.name }}
          # The build-args MUST be an EXACT match between the image cache and other workflow steps that want to use that cache.
          # This means that even the MAKEFLAGS have to be an EXACT match.
          # If the build-args are not an EXACT match, it will result in a cache miss, which will require GRPC to be built from scratch.
          # This is why some build args like GRPC_VERSION and MAKEFLAGS are hardcoded
          build-args: |
            BUILD_TYPE=${{ inputs.build-type }}
            CUDA_MAJOR_VERSION=${{ inputs.cuda-major-version }}
            CUDA_MINOR_VERSION=${{ inputs.cuda-minor-version }}
            FFMPEG=${{ inputs.ffmpeg }}
            IMAGE_TYPE=${{ inputs.image-type }}
            BASE_IMAGE=${{ inputs.base-image }}
            GRPC_BASE_IMAGE=${{ inputs.grpc-base-image || inputs.base-image }}
            GRPC_MAKEFLAGS=--jobs=4 --output-sync=target
            GRPC_VERSION=v1.64.0
            MAKEFLAGS=${{ inputs.makeflags }}
          context: .
          file: ./Dockerfile
          cache-from: type=gha
          platforms: ${{ inputs.platforms }}
          push: ${{ github.event_name != 'pull_request' }}
          tags: ${{ steps.meta.outputs.tags }}
          labels: ${{ steps.meta.outputs.labels }}

      - name: Build and push AIO image
        if: inputs.aio != ''
        uses: docker/build-push-action@v5
        with:
          builder: ${{ steps.buildx.outputs.name }}
          build-args: |
            BASE_IMAGE=quay.io/go-skynet/local-ai:${{ steps.meta.outputs.version }}
            MAKEFLAGS=${{ inputs.makeflags }}
          context: .
          file: ./Dockerfile.aio
          platforms: ${{ inputs.platforms }}
          push: ${{ github.event_name != 'pull_request' }}
          tags: ${{ steps.meta_aio.outputs.tags }}
          labels: ${{ steps.meta_aio.outputs.labels }}

      - name: Build and push AIO image (dockerhub)
        if: inputs.aio != ''
        uses: docker/build-push-action@v5
        with:
          builder: ${{ steps.buildx.outputs.name }}
          build-args: |
            BASE_IMAGE=localai/localai:${{ steps.meta.outputs.version }}
            MAKEFLAGS=${{ inputs.makeflags }}
          context: .
          file: ./Dockerfile.aio
          platforms: ${{ inputs.platforms }}
          push: ${{ github.event_name != 'pull_request' }}
          tags: ${{ steps.meta_aio_dockerhub.outputs.tags }}
          labels: ${{ steps.meta_aio_dockerhub.outputs.labels }}

      - name: Latest tag
        # run this on branches, when it is a tag and there is a latest-image defined
        if: github.event_name != 'pull_request' && inputs.latest-image != ''  && github.ref_type == 'tag'
        run: |
          docker pull localai/localai:${{ steps.meta.outputs.version }}
          docker tag localai/localai:${{ steps.meta.outputs.version }} localai/localai:${{ inputs.latest-image }}
          docker push localai/localai:${{ inputs.latest-image }}
          docker pull quay.io/go-skynet/local-ai:${{ steps.meta.outputs.version }}
          docker tag quay.io/go-skynet/local-ai:${{ steps.meta.outputs.version }} quay.io/go-skynet/local-ai:${{ inputs.latest-image }}
          docker push quay.io/go-skynet/local-ai:${{ inputs.latest-image }}
      - name: Latest AIO tag
        # run this on branches, when it is a tag and there is a latest-image defined
        if: github.event_name != 'pull_request' && inputs.latest-image-aio != ''  && github.ref_type == 'tag'
        run: |
          docker pull localai/localai:${{ steps.meta_aio_dockerhub.outputs.version }}
          docker tag localai/localai:${{ steps.meta_aio_dockerhub.outputs.version }} localai/localai:${{ inputs.latest-image-aio }}
          docker push localai/localai:${{ inputs.latest-image-aio }}
          docker pull quay.io/go-skynet/local-ai:${{ steps.meta_aio.outputs.version }}
          docker tag quay.io/go-skynet/local-ai:${{ steps.meta_aio.outputs.version }} quay.io/go-skynet/local-ai:${{ inputs.latest-image-aio }}
          docker push quay.io/go-skynet/local-ai:${{ inputs.latest-image-aio }}
  
      - name: job summary
        run: |
          echo "Built image: ${{ steps.meta.outputs.labels }}" >> $GITHUB_STEP_SUMMARY

      - name: job summary(AIO)
        if: inputs.aio != ''
        run: |
          echo "Built image: ${{ steps.meta_aio.outputs.labels }}" >> $GITHUB_STEP_SUMMARY
