ARTExplainer Docker Publisher

name: ARTExplainer Docker Publisher

on:
  push:
    # Publish `master` as Docker `latest` image.
    branches:
      - master

    # Publish `v1.2.3` tags as releases.
    tags:
      - v*

  # Run tests for any PRs.
  pull_request:

env:
  IMAGE_NAME: art-explainer

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

jobs:
  # Run tests.
  # See also https://docs.docker.com/docker-hub/builds/automated-testing/
  test:
    runs-on: ubuntu-latest

    steps:
      - name: Checkout source
        uses: actions/checkout@v4

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

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

      - name: Run tests
        uses: docker/build-push-action@v5
        with:
          platforms: linux/amd64, linux/arm64/v8
          context: python
          file: python/artexplainer.Dockerfile
          push: false
          # https://github.com/docker/buildx/issues/1533
          provenance: false

  # Push image to GitHub Packages.
  # See also https://docs.docker.com/docker-hub/builds/
  push:
    # Ensure test job passes before pushing image.
    needs: test

    runs-on: ubuntu-latest
    if: github.event_name == 'push'

    steps:
      - name: Checkout source
        uses: actions/checkout@v4

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

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

      - name: Login to DockerHub
        uses: docker/login-action@v3
        with:
          username: ${{ secrets.DOCKER_USER }}
          password: ${{ secrets.DOCKER_PASSWORD }}

      - name: Export version variable
        run: |
          IMAGE_ID=kserve/$IMAGE_NAME

          # Change all uppercase to lowercase
          IMAGE_ID=$(echo $IMAGE_ID | tr '[A-Z]' '[a-z]')

          # Strip git ref prefix from version
          VERSION=$(echo "${{ github.ref }}" | sed -e 's,.*/\(.*\),\1,')

          # Strip "v" prefix from tag name
          # [[ "${{ github.ref }}" == "refs/tags/"* ]] && VERSION=$(echo $VERSION | sed -e 's/^v//')

          # Use Docker `latest` tag convention
          [ "$VERSION" == "master" ] && VERSION=latest

          echo VERSION=$VERSION >> $GITHUB_ENV
          echo IMAGE_ID=$IMAGE_ID >> $GITHUB_ENV

      - name: Build and push
        uses: docker/build-push-action@v5
        with:
          platforms: linux/amd64, linux/arm64/v8
          context: python
          file: python/artexplainer.Dockerfile
          push: true
          tags: ${{ env.IMAGE_ID }}:${{ env.VERSION }}
          # https://github.com/docker/buildx/issues/1533
          provenance: false


Automated Release

name: Automated Release
on:
  workflow_dispatch:
    inputs:
      releaseBranch:
        description: 'The existing branch name to release from, e.g. release-0.12'
        required: true
      releaseTag:
        description: 'The release tag, e.g. v0.12.0-rc1'
        required: true

jobs:
  prepare-release:
    runs-on: ubuntu-latest
    steps:
      - name: Setup Go
        uses: actions/setup-go@v5
        with:
          go-version: 1.21

      - name: Checkout source code
        uses: actions/checkout@v4
        with:
          fetch-depth: 0
          ref: ${{ inputs.releaseBranch }}

      - name: Install dependencies
        run: |
          go mod download

      - name: Prepare Release
        shell: bash
        run: |
          GOPATH=$(go env GOPATH)
          KSERVE_PATH=$GOPATH/src/github.com/kserve/kserve
          echo "KSERVE_PATH=$KSERVE_PATH" >> "$GITHUB_ENV"
          mkdir -p $KSERVE_PATH
          cp -a . $KSERVE_PATH
          cd $KSERVE_PATH
          export RELEASE_BRANCH=${{ inputs.releaseBranch }}
          export RELEASE_TAG=${{ inputs.releaseTag }}

          # Bump Versions
          make bump-version
          ./hack/generate-install.sh $RELEASE_TAG
          ./hack/python-release.sh

          # Update Release Branch and Push Tag
          git diff
          git config --global user.email "terrytangyuan@gmail.com"
          git config --global user.name "terrytangyuan"
          git add -A
          git commit -m "Prepare release" || exit 0
          git push

      - name: Release
        uses: softprops/action-gh-release@v1
        with:
          prerelease: ${{ contains(inputs.releaseTag, 'rc') }}
          target_commitish: ${{ inputs.releaseBranch }}
          tag_name: ${{ inputs.releaseTag }}
        env:
          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}


Cherry Pick On Comment

name: Cherry Pick On Comment

on:
  issue_comment:
    types: [created]

jobs:
  cherry-pick:

    name: Cherry Pick
    if: github.event.issue.pull_request != '' && contains(github.event.comment.body, '/cherry-pick') && github.event.comment.author_association == 'CONTRIBUTOR'
    runs-on: ubuntu-latest

    steps:
      - name: Checkout the latest code
        uses: actions/checkout@v2
        with:
          token: ${{ secrets.GITHUB_TOKEN }}
          fetch-depth: 0 # otherwise, you will fail to push refs to dest repo
      - name: Automatic Cherry Pick
        uses: hianhianhian/gha-cherry-pick@master
        env:
          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}


Custom model gRPC Docker Publisher

name: Custom model gRPC Docker Publisher

on:
  push:
    # Publish `master` as Docker `latest` image.
    branches:
      - master

  # Run tests for any PRs.
  pull_request:

env:
  IMAGE_NAME: custom-model-grpc

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

jobs:
  # Run tests.
  # See also https://docs.docker.com/docker-hub/builds/automated-testing/
  test:
    runs-on: ubuntu-latest

    steps:
      - name: Checkout source
        uses: actions/checkout@v4

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

      - name: Run tests
        uses: docker/build-push-action@v5
        with:
          platforms: linux/amd64
          context: python
          file: python/custom_model_grpc.Dockerfile
          push: false
          # https://github.com/docker/buildx/issues/1533
          provenance: false

  # Push image to GitHub Packages.
  # See also https://docs.docker.com/docker-hub/builds/
  push:
    # Ensure test job passes before pushing image.
    needs: test

    runs-on: ubuntu-latest
    if: github.event_name == 'push'

    steps:
      - name: Checkout source
        uses: actions/checkout@v4

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

      - name: Login to DockerHub
        uses: docker/login-action@v3
        with:
          username: ${{ secrets.DOCKER_USER }}
          password: ${{ secrets.DOCKER_PASSWORD }}

      - name: Export version variable
        run: |
          IMAGE_ID=kserve/$IMAGE_NAME

          # Change all uppercase to lowercase
          IMAGE_ID=$(echo $IMAGE_ID | tr '[A-Z]' '[a-z]')

          # Strip git ref prefix from version
          VERSION=$(echo "${{ github.ref }}" | sed -e 's,.*/\(.*\),\1,')

          # Strip "v" prefix from tag name
          # [[ "${{ github.ref }}" == "refs/tags/"* ]] && VERSION=$(echo $VERSION | sed -e 's/^v//')

          # Use Docker `latest` tag convention
          [ "$VERSION" == "master" ] && VERSION=latest

          echo VERSION=$VERSION >> $GITHUB_ENV
          echo IMAGE_ID=$IMAGE_ID >> $GITHUB_ENV

      - name: Build and push
        uses: docker/build-push-action@v5
        with:
          platforms: linux/amd64
          context: python
          file: python/custom_model_grpc.Dockerfile
          push: true
          tags: ${{ env.IMAGE_ID }}:${{ env.VERSION }}
          # https://github.com/docker/buildx/issues/1533
          provenance: false


E2E Tests

name: E2E Tests

on:
  pull_request:
    branches: [master, release*]
    paths:
      - "**"
      - "!.github/**"
      - "!docs/**"
      - "!**.md"
      - ".github/workflows/e2e-test.yml"
  workflow_dispatch:

env:
  GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
  DOCKER_IMAGES_PATH: "/mnt/docker-images"
  DOCKER_REPO: "kserve"
  # artifact prefixes for bulk download
  PREDICTOR_ARTIFACT_PREFIX: "pred"
  EXPLAINER_ARTIFACT_PREFIX: "exp"
  TRANSFORMER_ARTIFACT_PREFIX: "trans"
  GRAPH_ARTIFACT_PREFIX: "graph"
  BASE_ARTIFACT_PREFIX: "base"
  # Controller images
  CONTROLLER_IMG: "kserve-controller"
  STORAGE_INIT_IMG: "storage-initializer"
  AGENT_IMG: "agent"
  ROUTER_IMG: "router"
  # Predictor runtime server images
  SKLEARN_IMG: "sklearnserver"
  XGB_IMG: "xgbserver"
  LGB_IMG: "lgbserver"
  PMML_IMG: "pmmlserver"
  PADDLE_IMG: "paddleserver"
  CUSTOM_MODEL_GRPC_IMG: "custom-model-grpc"
  HUGGINGFACE_IMG: "huggingfaceserver"
  # Explainer images
  ART_IMG: "art-explainer"
  # Transformer images
  IMAGE_TRANSFORMER_IMG: "image-transformer"
  IMAGE_TRANSFORMER_IMG_TAG: "kserve/image-transformer:${{ github.sha }}"
  CUSTOM_TRANSFORMER_GRPC_IMG: "custom-image-transformer-grpc"
  # Graph images
  SUCCESS_200_ISVC_IMG: "success-200-isvc"
  ERROR_404_ISVC_IMG: "error-404-isvc"

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

jobs:
  kserve-image-build:
    runs-on: ubuntu-latest
    steps:
      - name: Checkout source
        uses: actions/checkout@v4

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

      - name: Build KServe images
        run: |
          sudo mkdir -p ${DOCKER_IMAGES_PATH}
          sudo chown -R $USER ${DOCKER_IMAGES_PATH}
          ./test/scripts/gh-actions/build-images.sh
          docker image ls
          sudo ls -lh ${DOCKER_IMAGES_PATH}

      - name: Upload controller image
        uses: actions/upload-artifact@v4
        with:
          name: ${{ env.BASE_ARTIFACT_PREFIX }}-${{ env.CONTROLLER_IMG }}-${{ github.sha }}
          path: ${{ env.DOCKER_IMAGES_PATH }}/${{ env.CONTROLLER_IMG }}-${{ github.sha }}
          compression-level: 0
          if-no-files-found: error

      - name: Upload agent image
        uses: actions/upload-artifact@v4
        with:
          name: ${{ env.BASE_ARTIFACT_PREFIX }}-${{ env.AGENT_IMG }}-${{ github.sha }}
          path: ${{ env.DOCKER_IMAGES_PATH }}/${{ env.AGENT_IMG }}-${{ github.sha }}
          compression-level: 0
          if-no-files-found: error

      - name: Upload storage initializer image
        uses: actions/upload-artifact@v4
        with:
          name: ${{ env.BASE_ARTIFACT_PREFIX }}-${{ env.STORAGE_INIT_IMG }}-${{ github.sha }}
          path: ${{ env.DOCKER_IMAGES_PATH }}/${{ env.STORAGE_INIT_IMG }}-${{ github.sha }}
          compression-level: 0
          if-no-files-found: error

      - name: Upload router image
        uses: actions/upload-artifact@v4
        with:
          name: ${{ env.BASE_ARTIFACT_PREFIX }}-${{ env.ROUTER_IMG }}-${{ github.sha }}
          path: ${{ env.DOCKER_IMAGES_PATH }}/${{ env.ROUTER_IMG }}-${{ github.sha }}
          compression-level: 0
          if-no-files-found: error

  poetry-check:
    runs-on: ubuntu-latest
    steps:
      - name: Checkout source
        uses: actions/checkout@v4

      - name: Setup Python
        uses: actions/setup-python@v5
        with:
          python-version: "3.9"

      - name: Install Poetry and version plugin
        run: ./test/scripts/gh-actions/setup-poetry.sh

      - name: Check poetry lock file consistency
        run: ./test/scripts/gh-actions/check-poetry-lockfile.sh

  predictor-runtime-build:
    runs-on: ubuntu-latest
    needs: [poetry-check]
    steps:
      - name: Checkout source
        uses: actions/checkout@v4

      - name: Free-up disk space
        uses: ./.github/actions/free-up-disk-space

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

      - name: Build runtime server images
        run: |
          sudo mkdir -p ${DOCKER_IMAGES_PATH}
          sudo chown -R $USER ${DOCKER_IMAGES_PATH}
          ./test/scripts/gh-actions/build-server-runtimes.sh predictor,transformer
          docker image ls
          sudo ls -lh ${DOCKER_IMAGES_PATH}

      - name: Upload sklearn artifact
        uses: actions/upload-artifact@v4
        with:
          name: ${{ env.PREDICTOR_ARTIFACT_PREFIX }}-${{ env.SKLEARN_IMG }}-${{ github.sha }}
          path: ${{ env.DOCKER_IMAGES_PATH }}/${{ env.SKLEARN_IMG }}-${{ github.sha }}
          compression-level: 0
          if-no-files-found: error

      - name: Upload xgb server image
        uses: actions/upload-artifact@v4
        with:
          name: ${{ env.PREDICTOR_ARTIFACT_PREFIX }}-${{ env.XGB_IMG }}-${{ github.sha }}
          path: ${{ env.DOCKER_IMAGES_PATH }}/${{ env.XGB_IMG }}-${{ github.sha }}
          compression-level: 0
          if-no-files-found: error

      - name: Upload lgb server image
        uses: actions/upload-artifact@v4
        with:
          name: ${{ env.PREDICTOR_ARTIFACT_PREFIX }}-${{ env.LGB_IMG }}-${{ github.sha }}
          path: ${{ env.DOCKER_IMAGES_PATH }}/${{ env.LGB_IMG }}-${{ github.sha }}
          compression-level: 0
          if-no-files-found: error

      - name: Upload pmml server image
        uses: actions/upload-artifact@v4
        with:
          name: ${{ env.PREDICTOR_ARTIFACT_PREFIX }}-${{ env.PMML_IMG }}-${{ github.sha }}
          path: ${{ env.DOCKER_IMAGES_PATH }}/${{ env.PMML_IMG }}-${{ github.sha }}
          compression-level: 0
          if-no-files-found: error

      - name: Upload paddle image
        uses: actions/upload-artifact@v4
        with:
          name: ${{ env.PREDICTOR_ARTIFACT_PREFIX }}-${{ env.PADDLE_IMG }}-${{ github.sha }}
          path: ${{ env.DOCKER_IMAGES_PATH }}/${{ env.PADDLE_IMG }}-${{ github.sha }}
          compression-level: 0
          if-no-files-found: error

      - name: Upload image transformer image
        uses: actions/upload-artifact@v4
        with:
          name: ${{ env.TRANSFORMER_ARTIFACT_PREFIX }}-${{ env.IMAGE_TRANSFORMER_IMG }}-${{ github.sha }}
          path: ${{ env.DOCKER_IMAGES_PATH }}/${{ env.IMAGE_TRANSFORMER_IMG }}-${{ github.sha }}
          compression-level: 0
          if-no-files-found: error

      - name: Upload custom model grpc image
        uses: actions/upload-artifact@v4
        with:
          name: ${{ env.PREDICTOR_ARTIFACT_PREFIX }}-${{ env.CUSTOM_MODEL_GRPC_IMG }}-${{ github.sha }}
          path: ${{ env.DOCKER_IMAGES_PATH }}/${{ env.CUSTOM_MODEL_GRPC_IMG }}-${{ github.sha }}
          compression-level: 0
          if-no-files-found: error

      - name: Upload custom model transformer grpc image
        uses: actions/upload-artifact@v4
        with:
          name: ${{ env.TRANSFORMER_ARTIFACT_PREFIX }}-${{ env.CUSTOM_TRANSFORMER_GRPC_IMG }}-${{ github.sha }}
          path: ${{ env.DOCKER_IMAGES_PATH }}/${{ env.CUSTOM_TRANSFORMER_GRPC_IMG }}-${{ github.sha }}
          compression-level: 0
          if-no-files-found: error

      - name: Upload huggingface image
        uses: actions/upload-artifact@v4
        with:
          name: ${{ env.HUGGINGFACE_IMG }}-${{ github.sha }}
          path: ${{ env.DOCKER_IMAGES_PATH }}/${{ env.HUGGINGFACE_IMG }}-${{ github.sha }}
          compression-level: 0
          if-no-files-found: error

  explainer-runtime-build:
    runs-on: ubuntu-latest
    needs: [poetry-check]
    steps:
      - name: Checkout source
        uses: actions/checkout@v4

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

      - name: Build runtime server images
        run: |
          sudo mkdir -p ${DOCKER_IMAGES_PATH}
          sudo chown -R $USER ${DOCKER_IMAGES_PATH}
          ./test/scripts/gh-actions/build-server-runtimes.sh explainer
          docker image ls
          sudo ls -lh ${DOCKER_IMAGES_PATH}

      - name: Upload art explainer image
        uses: actions/upload-artifact@v4
        with:
          name: ${{ env.EXPLAINER_ARTIFACT_PREFIX }}-${{ env.ART_IMG }}-${{ github.sha }}
          path: ${{ env.DOCKER_IMAGES_PATH }}/${{ env.ART_IMG }}-${{ github.sha }}
          compression-level: 0
          if-no-files-found: error

  graph-tests-images-build:
    runs-on: ubuntu-latest
    needs: [poetry-check]
    steps:
      - name: Checkout source
        uses: actions/checkout@v4

      - name: Free-up disk space
        uses: ./.github/actions/free-up-disk-space

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

      - name: Build test images needed for graph tests
        run: |
          sudo mkdir -p ${DOCKER_IMAGES_PATH}
          sudo chown -R $USER ${DOCKER_IMAGES_PATH}
          ./test/scripts/gh-actions/build-graph-tests-images.sh
          docker image ls
          sudo ls -lh ${DOCKER_IMAGES_PATH}

      - name: Upload success_200_isvc predictor image
        uses: actions/upload-artifact@v4
        with:
          name: ${{ env.GRAPH_ARTIFACT_PREFIX }}-${{ env.SUCCESS_200_ISVC_IMG }}-${{ github.sha }}
          path: ${{ env.DOCKER_IMAGES_PATH }}/${{ env.SUCCESS_200_ISVC_IMG }}-${{ github.sha }}
          compression-level: 0
          if-no-files-found: error

      - name: Upload error_404_isvc predictor image
        uses: actions/upload-artifact@v4
        with:
          name: ${{ env.GRAPH_ARTIFACT_PREFIX }}-${{ env.ERROR_404_ISVC_IMG }}-${{ github.sha }}
          path: ${{ env.DOCKER_IMAGES_PATH }}/${{ env.ERROR_404_ISVC_IMG }}-${{ github.sha }}
          compression-level: 0
          if-no-files-found: error

  test-predictor:
    runs-on: ubuntu-latest
    needs:
      [
        kserve-image-build,
        predictor-runtime-build,
      ]
    steps:
      - name: Checkout
        uses: actions/checkout@v4

      - name: Free-up disk space
        uses: ./.github/actions/free-up-disk-space

      - name: Setup Go
        uses: actions/setup-go@v5
        with:
          go-version: "1.21"

      - name: Setup Python
        uses: actions/setup-python@v5
        with:
          python-version: "3.9"

      - name: Setup Minikube
        uses: ./.github/actions/minikube-setup

      - name: KServe dependency setup
        uses: ./.github/actions/kserve-dep-setup

      - name: Download base images
        uses: ./.github/actions/base-download

      - name: Download predictor artifacts
        uses: actions/download-artifact@v4
        with:
          path: ./tmp
          pattern: ${{ env.PREDICTOR_ARTIFACT_PREFIX }}-*
          merge-multiple: true

      - name: Load docker images
        uses: ./.github/actions/load-docker-images
        with:
          directory: ./tmp

      - name: Install Poetry and version plugin
        run: ./test/scripts/gh-actions/setup-poetry.sh

      - name: Install KServe
        run: |
          ./test/scripts/gh-actions/setup-kserve.sh

          kubectl get pods -n kserve
          kubectl describe pods -n kserve

      - name: Run predictor E2E tests
        timeout-minutes: 40
        run: |
          ./test/scripts/gh-actions/run-e2e-tests.sh "predictor" "6"

      - name: Check system status
        if: always()
        run: |
          ./test/scripts/gh-actions/status-check.sh

  test-transformer-explainer-mms:
    runs-on: ubuntu-latest
    needs:
      [kserve-image-build, predictor-runtime-build, explainer-runtime-build]
    steps:
      - name: Checkout source
        uses: actions/checkout@v4

      - name: Free-up disk space
        uses: ./.github/actions/free-up-disk-space

      - name: Setup Go
        uses: actions/setup-go@v5
        with:
          go-version: "1.21"
      - name: Setup Python
        uses: actions/setup-python@v5
        with:
          python-version: "3.9"

      - name: Setup Minikube
        uses: ./.github/actions/minikube-setup

      - name: KServe dependency setup
        uses: ./.github/actions/kserve-dep-setup

      - name: Download base images
        uses: ./.github/actions/base-download

      - name: Download transformer and explainer artifacts
        uses: actions/download-artifact@v4
        with:
          path: ./tmp
          pattern: +(${{ env.TRANSFORMER_ARTIFACT_PREFIX }}|${{ env.EXPLAINER_ARTIFACT_PREFIX }})-*
          merge-multiple: true

      - name: Download sklearn server image
        uses: actions/download-artifact@v4
        with:
          name: ${{ env.PREDICTOR_ARTIFACT_PREFIX }}-${{ env.SKLEARN_IMG }}-${{ github.sha }}
          path: ./tmp

      - name: Download custom model grpc image
        uses: actions/download-artifact@v4
        with:
          name: ${{ env.PREDICTOR_ARTIFACT_PREFIX }}-${{ env.CUSTOM_MODEL_GRPC_IMG }}-${{ github.sha }}
          path: ./tmp

      - name: Download xgb server image
        uses: actions/download-artifact@v4
        with:
          name: ${{ env.PREDICTOR_ARTIFACT_PREFIX }}-${{ env.XGB_IMG }}-${{ github.sha }}
          path: ./tmp

      - name: Load docker images
        uses: ./.github/actions/load-docker-images
        with:
          directory: ./tmp

      - name: Install Poetry and version plugin
        run: ./test/scripts/gh-actions/setup-poetry.sh

      - name: Install KServe
        run: |
          ./test/scripts/gh-actions/setup-kserve.sh

          kubectl get pods -n kserve
          kubectl describe pods -n kserve

      - name: Run E2E tests
        timeout-minutes: 30
        run: |
          ./test/scripts/gh-actions/run-e2e-tests.sh "transformer or mms or collocation or explainer" "6"

      - name: Check system status
        if: always()
        run: |
          ./test/scripts/gh-actions/status-check.sh

  test-graph:
    runs-on: ubuntu-latest
    needs:
      [
        kserve-image-build,
        predictor-runtime-build,
        graph-tests-images-build,
      ]
    steps:
      - name: Checkout
        uses: actions/checkout@v4

      - name: Setup Go
        uses: actions/setup-go@v5
        with:
          go-version: "1.21"

      - name: Setup Python
        uses: actions/setup-python@v5
        with:
          python-version: "3.9"

      - name: Free-up disk space
        uses: ./.github/actions/free-up-disk-space

      - name: Setup Minikube
        uses: ./.github/actions/minikube-setup

      - name: Download base images
        uses: ./.github/actions/base-download

      - name: KServe dependency setup
        uses: ./.github/actions/kserve-dep-setup

      - name: Download graph artifacts
        uses: actions/download-artifact@v4
        with:
          path: ./tmp
          pattern: ${{ env.GRAPH_ARTIFACT_PREFIX }}-*
          merge-multiple: true

      - name: Download sklearn server image
        uses: actions/download-artifact@v4
        with:
          name: ${{ env.PREDICTOR_ARTIFACT_PREFIX }}-${{ env.SKLEARN_IMG }}-${{ github.sha }}
          path: ./tmp

      - name: Download xgb server image
        uses: actions/download-artifact@v4
        with:
          name: ${{ env.PREDICTOR_ARTIFACT_PREFIX }}-${{ env.XGB_IMG }}-${{ github.sha }}
          path: ./tmp

      - name: Load docker images
        uses: ./.github/actions/load-docker-images
        with:
          directory: ./tmp

      - name: Install Poetry and version plugin
        run: ./test/scripts/gh-actions/setup-poetry.sh

      - name: Install KServe
        run: |
          ./test/scripts/gh-actions/setup-kserve.sh

          kubectl get pods -n kserve
          kubectl describe pods -n kserve

      - name: Run E2E tests for graph
        timeout-minutes: 30
        run: |
          ./test/scripts/gh-actions/run-e2e-tests.sh "graph" "6"

      - name: Check system status
        if: always()
        run: |
          ./test/scripts/gh-actions/status-check.sh

  test-path-based-routing:
    runs-on: ubuntu-latest
    needs:
      [
        kserve-image-build,
        predictor-runtime-build
      ]
    steps:
      - name: Checkout
        uses: actions/checkout@v4

      - name: Setup Go
        uses: actions/setup-go@v5
        with:
          go-version: "1.21"

      - name: Setup Python
        uses: actions/setup-python@v5
        with:
          python-version: "3.9"

      - name: Free-up disk space
        uses: ./.github/actions/free-up-disk-space

      - name: Setup Minikube
        uses: ./.github/actions/minikube-setup

      - name: Download base images
        uses: ./.github/actions/base-download

      - name: KServe dependency setup
        uses: ./.github/actions/kserve-dep-setup

      - name: Download sklearn server image
        uses: actions/download-artifact@v4
        with:
          name: ${{ env.PREDICTOR_ARTIFACT_PREFIX }}-${{ env.SKLEARN_IMG }}-${{ github.sha }}
          path: ./tmp

      - name: Download xgb server image
        uses: actions/download-artifact@v4
        with:
          name: ${{ env.PREDICTOR_ARTIFACT_PREFIX }}-${{ env.XGB_IMG }}-${{ github.sha }}
          path: ./tmp

      - name: Download lgb server image
        uses: actions/download-artifact@v4
        with:
          name: ${{ env.PREDICTOR_ARTIFACT_PREFIX }}-${{ env.LGB_IMG }}-${{ github.sha }}
          path: ./tmp

      - name: Download transformer image
        uses: actions/download-artifact@v4
        with:
          name: ${{ env.TRANSFORMER_ARTIFACT_PREFIX }}-${{ env.IMAGE_TRANSFORMER_IMG }}-${{ github.sha }}
          path: ./tmp

      - name: Load docker images
        uses: ./.github/actions/load-docker-images
        with:
          directory: ./tmp

      - name: Install Poetry and version plugin
        run: ./test/scripts/gh-actions/setup-poetry.sh

      - name: Install KServe
        run: |
          ./test/scripts/gh-actions/setup-kserve.sh

          kubectl get pods -n kserve
          kubectl describe pods -n kserve

      - name: Patch inferenceservice config
        run: |
          kubectl patch configmaps -n kserve inferenceservice-config --patch-file config/overlays/test/configmap/inferenceservice-ingress.yaml
          kubectl describe configmaps -n kserve inferenceservice-config

      - name: Run E2E tests with path-based routing
        timeout-minutes: 30
        run: |
          ./test/scripts/gh-actions/run-e2e-tests.sh "path_based_routing" "6"

      - name: Check system status
        if: always()
        run: |
          ./test/scripts/gh-actions/status-check.sh

  test-qpext:
    runs-on: ubuntu-latest
    needs: [kserve-image-build, predictor-runtime-build]
    steps:
      - name: Checkout source
        uses: actions/checkout@v4

      - name: Free-up disk space
        uses: ./.github/actions/free-up-disk-space

      - name: Setup Go
        uses: actions/setup-go@v5
        with:
          go-version: "1.21"
      - name: Setup Python
        uses: actions/setup-python@v5
        with:
          python-version: "3.9"

      - name: Setup Minikube
        uses: ./.github/actions/minikube-setup

      - name: KServe dependency setup
        uses: ./.github/actions/kserve-dep-setup

      - name: Download base images
        uses: ./.github/actions/base-download

      - name: Build queue proxy extension image
        run: |
          ./test/scripts/gh-actions/build-qpext-image.sh
          docker image ls

      - name: Download sklearn server image
        uses: actions/download-artifact@v4
        with:
          name: ${{ env.PREDICTOR_ARTIFACT_PREFIX }}-${{ env.SKLEARN_IMG }}-${{ github.sha }}
          path: ./tmp

      - name: Load docker images
        uses: ./.github/actions/load-docker-images
        with:
          directory: ./tmp

      - name: Install Poetry and version plugin
        run: ./test/scripts/gh-actions/setup-poetry.sh
      - name: Install KServe
        run: |
          ./test/scripts/gh-actions/setup-kserve.sh
          kubectl get pods -n kserve
          kubectl describe pods -n kserve
      - name: Patch qpext image
        run: |
          kubectl patch configmaps -n knative-serving config-deployment --patch '{"data": {"queue-sidecar-image": "kserve/qpext:${{ github.sha }}"}}'
          kubectl describe configmaps -n knative-serving config-deployment
      - name: Run queue proxy extension E2E tests
        timeout-minutes: 30
        run: |
          ./test/scripts/gh-actions/run-qpext-test.sh

      - name: Check system status
        if: always()
        run: |
          ./test/scripts/gh-actions/status-check.sh

  test-with-helm:
    runs-on: ubuntu-latest
    needs:
      [kserve-image-build]
    steps:
      - name: Checkout source
        uses: actions/checkout@v4
      - name: Setup Go
        uses: actions/setup-go@v5
        with:
          go-version: "1.21"
      - name: Setup Python
        uses: actions/setup-python@v5
        with:
          python-version: "3.9"

      - uses: ./.github/actions/free-up-disk-space
      - name: Setup Minikube
        uses: ./.github/actions/minikube-setup

      - name: KServe dependency setup
        uses: ./.github/actions/kserve-dep-setup

      - name: Download base images
        uses: ./.github/actions/base-download

      - name: Install Poetry and version plugin
        run: ./test/scripts/gh-actions/setup-poetry.sh

      - name: Install Kserve from helm
        run: |
          ./test/scripts/gh-actions/setup-modelmesh-dep.sh
          ./test/scripts/gh-actions/setup-kserve-helm.sh
          kubectl get pods -n kserve
          kubectl describe pods -n kserve

      - name: Run E2E tests
        timeout-minutes: 20
        run: |
          ./test/scripts/gh-actions/run-e2e-tests.sh "helm"
          kubectl get pods -n kserve

      - name: Check system status
        if: always()
        run: |
          ./test/scripts/gh-actions/status-check.sh

  test-raw:
    runs-on: ubuntu-latest
    needs:
      [kserve-image-build, predictor-runtime-build]
    steps:
      - name: Checkout source
        uses: actions/checkout@v4

      - name: Free-up disk space
        uses: ./.github/actions/free-up-disk-space

      - name: Setup Go
        uses: actions/setup-go@v5
        with:
          go-version: "1.21"
      - name: Setup Python
        uses: actions/setup-python@v5
        with:
          python-version: "3.9"

      - name: Setup Minikube
        uses: ./.github/actions/minikube-setup

      - name: KServe dependency setup
        uses: ./.github/actions/kserve-dep-setup
        with:
          deployment-mode: "raw"

      - name: Download base images
        uses: ./.github/actions/base-download

      - name: Download sklearn server image
        uses: actions/download-artifact@v4
        with:
          name: ${{ env.PREDICTOR_ARTIFACT_PREFIX }}-${{ env.SKLEARN_IMG }}-${{ github.sha }}
          path: ./tmp

      - name: Download xgb server image
        uses: actions/download-artifact@v4
        with:
          name: ${{ env.PREDICTOR_ARTIFACT_PREFIX }}-${{ env.XGB_IMG }}-${{ github.sha }}
          path: ./tmp

      - name: Download custom model grpc image
        uses: actions/download-artifact@v4
        with:
          name: ${{ env.PREDICTOR_ARTIFACT_PREFIX }}-${{ env.CUSTOM_MODEL_GRPC_IMG }}-${{ github.sha }}
          path: ./tmp

      - name: Download transformer image
        uses: actions/download-artifact@v4
        with:
          name: ${{ env.TRANSFORMER_ARTIFACT_PREFIX }}-${{ env.IMAGE_TRANSFORMER_IMG }}-${{ github.sha }}
          path: ./tmp

      - name: Load docker images
        uses: ./.github/actions/load-docker-images
        with:
          directory: ./tmp

      - name: Install Poetry and version plugin
        run: ./test/scripts/gh-actions/setup-poetry.sh

      - name: Install KServe
        run: |
          ./test/scripts/gh-actions/setup-kserve.sh "raw"

          kubectl get pods -n kserve
          kubectl describe pods -n kserve

      - name: Run E2E tests
        timeout-minutes: 30
        run: |
          ./test/scripts/gh-actions/run-e2e-tests.sh "raw" "6"

      - name: Check system status
        if: always()
        run: |
          ./test/scripts/gh-actions/status-check.sh

  test-kourier:
    runs-on: ubuntu-latest
    needs:
      [kserve-image-build, predictor-runtime-build, graph-tests-images-build]
    steps:
      - name: Checkout source
        uses: actions/checkout@v4

      - name: Free-up disk space
        uses: ./.github/actions/free-up-disk-space

      - name: Setup Go
        uses: actions/setup-go@v5
        with:
          go-version: "1.21"
      - name: Setup Python
        uses: actions/setup-python@v5
        with:
          python-version: "3.9"

      - name: Setup Minikube
        uses: ./.github/actions/minikube-setup

      - name: KServe dependency setup
        uses: ./.github/actions/kserve-dep-setup
        with:
          network-layer: "kourier"

      - name: Download base images
        uses: ./.github/actions/base-download

      - name: Download graph artifacts
        uses: actions/download-artifact@v4
        with:
          path: ./tmp
          pattern: ${{ env.GRAPH_ARTIFACT_PREFIX }}-*
          merge-multiple: true

      - name: Download sklearn server image
        uses: actions/download-artifact@v4
        with:
          name: ${{ env.PREDICTOR_ARTIFACT_PREFIX }}-${{ env.SKLEARN_IMG }}-${{ github.sha }}
          path: ./tmp

      - name: Download xgb server image
        uses: actions/download-artifact@v4
        with:
          name: ${{ env.PREDICTOR_ARTIFACT_PREFIX }}-${{ env.XGB_IMG }}-${{ github.sha }}
          path: ./tmp

      - name: Load docker images
        uses: ./.github/actions/load-docker-images
        with:
          directory: ./tmp

      - name: Install Poetry and version plugin
        run: ./test/scripts/gh-actions/setup-poetry.sh

      - name: Install KServe
        run: |
          ./test/scripts/gh-actions/setup-kserve.sh

          kubectl get pods -n kserve
          kubectl describe pods -n kserve

      - name: Patch inferenceservice config to disable istio
        run: |
          kubectl patch configmaps -n kserve inferenceservice-config --patch-file config/overlays/test/configmap/inferenceservice-disable-istio.yaml
          kubectl describe configmaps -n kserve inferenceservice-config

      - name: Run E2E tests
        timeout-minutes: 30
        run: |
          export KSERVE_INGRESS_HOST_PORT=$(kubectl get pod -n knative-serving -l "app=3scale-kourier-gateway" \
          --output=jsonpath="{.items[0].status.podIP}"):$(kubectl get pod -n knative-serving -l "app=3scale-kourier-gateway" \
          --output=jsonpath="{.items[0].spec.containers[0].ports[0].containerPort}")

          ./test/scripts/gh-actions/run-e2e-tests.sh "kourier" "6"

      - name: Check system status
        if: always()
        run: |
          ./test/scripts/gh-actions/status-check.sh "kourier"

  test-llm:
    runs-on: ubuntu-latest
    needs:
      [ kserve-image-build, predictor-runtime-build]
    steps:
      - name: Checkout source
        uses: actions/checkout@v4

      - name: Free-up disk space
        uses: ./.github/actions/free-up-disk-space

      - name: Setup Go
        uses: actions/setup-go@v5
        with:
          go-version: "1.21"
      - name: Setup Python
        uses: actions/setup-python@v5
        with:
          python-version: "3.9"

      - name: Setup Minikube
        uses: ./.github/actions/minikube-setup

      - name: KServe dependency setup
        uses: ./.github/actions/kserve-dep-setup

      - name: Download base images
        uses: ./.github/actions/base-download

      - name: Download huggingface server image
        uses: actions/download-artifact@v4
        with:
          name: ${{ env.HUGGINGFACE_IMG }}-${{ github.sha }}
          path: ./tmp

      - name: Load docker images
        uses: ./.github/actions/load-docker-images
        with:
          directory: ./tmp

      - name: Install Poetry and version plugin
        run: ./test/scripts/gh-actions/setup-poetry.sh

      - name: Install KServe
        run: |
          ./test/scripts/gh-actions/setup-kserve.sh

          kubectl get pods -n kserve
          kubectl describe pods -n kserve

      - name: Run E2E tests
        timeout-minutes: 30
        run: |
          ./test/scripts/gh-actions/run-e2e-tests.sh "llm" "2"

      - name: Check system status
        if: always()
        run: |
          ./test/scripts/gh-actions/status-check.sh


Go

name: Go

on:
  push:
    branches: [master, release*]
  pull_request:
    branches: []
  workflow_dispatch:

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

jobs:
  build:
    name: Build
    runs-on: ubuntu-latest
    steps:
      - name: Set up Go 1.x
        uses: actions/setup-go@v5
        with:
          go-version: "1.21"
        id: go

      - name: Check out code into the Go module directory
        uses: actions/checkout@v4

      - name: Get dependencies
        run: |
          go get -v -t -d ./...

      - name: Test
        id: test
        run: |
          export GOPATH=/home/runner/go
          export PATH=$PATH:/usr/local/kubebuilder/bin:/home/runner/go/bin
          wget -O $GOPATH/bin/yq https://github.com/mikefarah/yq/releases/download/v4.28.1/yq_linux_amd64
          chmod +x $GOPATH/bin/yq
          make test
          ./coverage.sh
          echo ::set-output name=coverage::$(./coverage.sh | tr -s '\t' | cut -d$'\t' -f 3)

      - name: Print coverage
        run: |
          echo "Coverage output is ${{ steps.test.outputs.coverage }}"

      - name: Update coverage badge
        if: github.ref == 'refs/heads/master'
        uses: schneegans/dynamic-badges-action@v1.7.0
        with:
          auth: ${{ secrets.GIST_SECRET }}
          gistID: 5174bd748ac63a6e4803afea902e9810
          filename: coverage.json
          label: coverage
          message: ${{ steps.test.outputs.coverage }}
          color: green


golangci-lint

name: golangci-lint
on:
  push:
    branches:
      - master
      - main
  pull_request:

permissions:
  contents: read
  pull-requests: read

jobs:
  golangci:
    name: lint
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-go@v5
        with:
          go-version: '1.21'
          cache: false
      - name: golangci-lint
        uses: golangci/golangci-lint-action@v4
        with:
          version: v1.56
          args: --out-format=line-number


helm-publish

name: helm-publish

on:
  release:
    types: [prereleased, released]

env:
  HELM_CHARTS_PATH: charts

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

permissions:
  contents: write
  packages: write

jobs:
  upload-helm-charts:
    runs-on: ubuntu-latest

    steps:
      - name: Checkout source
        uses: actions/checkout@v4

      - name: Setup Helm
        uses: azure/setup-helm@v4

      - name: Login to GHCR
        if: github.event_name != 'pull_request'
        uses: docker/login-action@v3
        with:
          registry: ghcr.io
          username: ${{ github.repository_owner }}
          password: ${{ secrets.GITHUB_TOKEN }}

      - name: Package helm charts
        run: for dir in ./*/; do helm package $dir; done
        working-directory: ${{ env.HELM_CHARTS_PATH }}

      - name: Push Charts to GHCR
        working-directory: ${{ env.HELM_CHARTS_PATH }}
        run: |
          for pkg in *.tgz; do
            if [ -z "${pkg:-}" ]; then
              break
            fi
            helm push "${pkg}" oci://ghcr.io/${GITHUB_REPOSITORY_OWNER}/charts
          done

      - name: Rename helm chart archives
        run: for filename in *.tgz; do mv "$filename" "helm-chart-$filename"; done
        working-directory: ${{ env.HELM_CHARTS_PATH }}

      - uses: softprops/action-gh-release@v1
        with:
          files: ${{ env.HELM_CHARTS_PATH }}/*.tgz


Huggingface Docker Publisher

name: Huggingface Docker Publisher

on:
  push:
    # Publish `master` as Docker `latest` image.
    branches:
      - master

    # Publish `v1.2.3` tags as releases.
    tags:
      - v*
  # Run tests for any PRs.
  pull_request:

env:
  IMAGE_NAME: huggingfaceserver

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

jobs:
  # Run tests.
  # See also https://docs.docker.com/docker-hub/builds/automated-testing/
  test:
    runs-on: ubuntu-latest

    steps:
      - name: Checkout source
        uses: actions/checkout@v4

      - name: Free-up disk space
        uses: ./.github/actions/free-up-disk-space

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

      - name: Run tests
        uses: docker/build-push-action@v5
        with:
          platforms: linux/amd64
          context: python
          file: python/huggingface_server.Dockerfile
          push: false
          # https://github.com/docker/buildx/issues/1533
          provenance: false

  # Push image to GitHub Packages.
  # See also https://docs.docker.com/docker-hub/builds/
  push:
    # Ensure test job passes before pushing image.
    needs: test

    runs-on: ubuntu-latest
    if: github.event_name == 'push'

    steps:
      - name: Checkout source
        uses: actions/checkout@v4

      - name: Free-up disk space
        uses: ./.github/actions/free-up-disk-space

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

      - name: Login to DockerHub
        uses: docker/login-action@v3
        with:
          username: ${{ secrets.DOCKER_USER }}
          password: ${{ secrets.DOCKER_PASSWORD }}

      - name: Export version variable
        run: |
          IMAGE_ID=kserve/$IMAGE_NAME

          # Change all uppercase to lowercase
          IMAGE_ID=$(echo $IMAGE_ID | tr '[A-Z]' '[a-z]')

          # Strip git ref prefix from version
          VERSION=$(echo "${{ github.ref }}" | sed -e 's,.*/\(.*\),\1,')

          # Strip "v" prefix from tag name
          # [[ "${{ github.ref }}" == "refs/tags/"* ]] && VERSION=$(echo $VERSION | sed -e 's/^v//')

          # Use Docker `latest` tag convention
          [ "$VERSION" == "master" ] && VERSION=latest

          echo VERSION=$VERSION >> $GITHUB_ENV
          echo IMAGE_ID=$IMAGE_ID >> $GITHUB_ENV

      - name: Build and push
        uses: docker/build-push-action@v5
        with:
          platforms: linux/amd64
          context: python
          file: python/huggingface_server.Dockerfile
          push: true
          tags: ${{ env.IMAGE_ID }}:${{ env.VERSION }}
          # https://github.com/docker/buildx/issues/1533
          provenance: false


Kserve controller Docker Publisher

name: Kserve controller Docker Publisher

on:
  push:
    # Publish `master` as Docker `latest` image.
    branches:
      - master

    # Publish `v1.2.3` tags as releases.
    tags:
      - v*

  # Run tests for any PRs.
  pull_request:

env:
  IMAGE_NAME: kserve-controller

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

jobs:
  # Run tests.
  # See also https://docs.docker.com/docker-hub/builds/automated-testing/
  test:
    runs-on: ubuntu-latest

    steps:
      - name: Checkout source
        uses: actions/checkout@v4

      - name: Run tests
        run: |
          if [ -f docker-compose.test.yml ]; then
            docker-compose --file docker-compose.test.yml build
            docker-compose --file docker-compose.test.yml run sut
          else
            docker buildx build . --file Dockerfile
          fi

  # Push image to GitHub Packages.
  # See also https://docs.docker.com/docker-hub/builds/
  push:
    # Ensure test job passes before pushing image.
    needs: test

    runs-on: ubuntu-latest
    if: github.event_name == 'push'

    steps:
      - name: Checkout source
        uses: actions/checkout@v4

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

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

      - name: Login to DockerHub
        uses: docker/login-action@v3
        with:
          username: ${{ secrets.DOCKER_USER }}
          password: ${{ secrets.DOCKER_PASSWORD }}

      - name: export version variable
        run: |
          IMAGE_ID=kserve/$IMAGE_NAME

          # Change all uppercase to lowercase
          IMAGE_ID=$(echo $IMAGE_ID | tr '[A-Z]' '[a-z]')

          # Strip git ref prefix from version
          VERSION=$(echo "${{ github.ref }}" | sed -e 's,.*/\(.*\),\1,')

          # Strip "v" prefix from tag name
          # [[ "${{ github.ref }}" == "refs/tags/"* ]] && VERSION=$(echo $VERSION | sed -e 's/^v//')

          # Use Docker `latest` tag convention
          [ "$VERSION" == "master" ] && VERSION=latest

          echo VERSION=$VERSION >> $GITHUB_ENV
          echo IMAGE_ID=$IMAGE_ID >> $GITHUB_ENV

      - name: Build and push
        uses: docker/build-push-action@v5
        with:
          platforms: linux/amd64,linux/arm/v7,linux/arm64/v8,linux/ppc64le,linux/s390x
          context: .
          file: Dockerfile
          push: true
          tags: ${{ env.IMAGE_ID }}:${{ env.VERSION }}
          # https://github.com/docker/buildx/issues/1533
          provenance: false


LightGBMServer Docker Publisher

name: LightGBMServer Docker Publisher

on:
  push:
    # Publish `master` as Docker `latest` image.
    branches:
      - master

    # Publish `v1.2.3` tags as releases.
    tags:
      - v*

  # Run tests for any PRs.
  pull_request:

env:
  IMAGE_NAME: lgbserver

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

jobs:
  # Run tests.
  # See also https://docs.docker.com/docker-hub/builds/automated-testing/
  test:
    runs-on: ubuntu-latest

    steps:
      - name: Checkout source
        uses: actions/checkout@v4

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

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

      - name: Run tests
        uses: docker/build-push-action@v5
        with:
          platforms: linux/amd64, linux/arm64/v8
          context: python
          file: python/lgb.Dockerfile
          push: false
          # https://github.com/docker/buildx/issues/1533
          provenance: false

  # Push image to GitHub Packages.
  # See also https://docs.docker.com/docker-hub/builds/
  push:
    # Ensure test job passes before pushing image.
    needs: test

    runs-on: ubuntu-latest
    if: github.event_name == 'push'

    steps:
      - name: Checkout source
        uses: actions/checkout@v4

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

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

      - name: Login to DockerHub
        uses: docker/login-action@v3
        with:
          username: ${{ secrets.DOCKER_USER }}
          password: ${{ secrets.DOCKER_PASSWORD }}

      - name: Export version variable
        run: |
          IMAGE_ID=kserve/$IMAGE_NAME

          # Change all uppercase to lowercase
          IMAGE_ID=$(echo $IMAGE_ID | tr '[A-Z]' '[a-z]')

          # Strip git ref prefix from version
          VERSION=$(echo "${{ github.ref }}" | sed -e 's,.*/\(.*\),\1,')

          # Strip "v" prefix from tag name
          # [[ "${{ github.ref }}" == "refs/tags/"* ]] && VERSION=$(echo $VERSION | sed -e 's/^v//')

          # Use Docker `latest` tag convention
          [ "$VERSION" == "master" ] && VERSION=latest

          echo VERSION=$VERSION >> $GITHUB_ENV
          echo IMAGE_ID=$IMAGE_ID >> $GITHUB_ENV

      - name: Build and push
        uses: docker/build-push-action@v5
        with:
          platforms: linux/amd64, linux/arm64/v8
          context: python
          file: python/lgb.Dockerfile
          push: true
          tags: ${{ env.IMAGE_ID }}:${{ env.VERSION }}
          # https://github.com/docker/buildx/issues/1533
          provenance: false


PaddleServer Docker Publisher

name: PaddleServer Docker Publisher

on:
  push:
    # Publish `master` as Docker `latest` image.
    branches:
      - master

    # Publish `v1.2.3` tags as releases.
    tags:
      - v*

  # Run tests for any PRs.
  pull_request:

env:
  IMAGE_NAME: paddleserver

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

jobs:
  # Run tests.
  # See also https://docs.docker.com/docker-hub/builds/automated-testing/
  test:
    runs-on: ubuntu-latest

    steps:
      - name: Checkout source
        uses: actions/checkout@v4

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

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

      - name: Run tests
        uses: docker/build-push-action@v5
        with:
          platforms: linux/amd64, linux/arm64/v8
          context: python
          file: python/paddle.Dockerfile
          push: false
          # https://github.com/docker/buildx/issues/1533
          provenance: false

  # Push image to GitHub Packages.
  # See also https://docs.docker.com/docker-hub/builds/
  push:
    # Ensure test job passes before pushing image.
    needs: test

    runs-on: ubuntu-latest
    if: github.event_name == 'push'

    steps:
      - name: Checkout source
        uses: actions/checkout@v4

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

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

      - name: Login to DockerHub
        uses: docker/login-action@v3
        with:
          username: ${{ secrets.DOCKER_USER }}
          password: ${{ secrets.DOCKER_PASSWORD }}

      - name: Export version variable
        run: |
          IMAGE_ID=kserve/$IMAGE_NAME

          # Change all uppercase to lowercase
          IMAGE_ID=$(echo $IMAGE_ID | tr '[A-Z]' '[a-z]')

          # Strip git ref prefix from version
          VERSION=$(echo "${{ github.ref }}" | sed -e 's,.*/\(.*\),\1,')

          # Strip "v" prefix from tag name
          # [[ "${{ github.ref }}" == "refs/tags/"* ]] && VERSION=$(echo $VERSION | sed -e 's/^v//')

          # Use Docker `latest` tag convention
          [ "$VERSION" == "master" ] && VERSION=latest

          echo VERSION=$VERSION >> $GITHUB_ENV
          echo IMAGE_ID=$IMAGE_ID >> $GITHUB_ENV

      - name: Build and push
        uses: docker/build-push-action@v5
        with:
          platforms: linux/amd64, linux/arm64/v8
          context: python
          file: python/paddle.Dockerfile
          push: true
          tags: ${{ env.IMAGE_ID }}:${{ env.VERSION }}
          # https://github.com/docker/buildx/issues/1533
          provenance: false


PMMLServer Docker Publisher

name: PMMLServer Docker Publisher

on:
  push:
    # Publish `master` as Docker `latest` image.
    branches:
      - master

    # Publish `v1.2.3` tags as releases.
    tags:
      - v*

  # Run tests for any PRs.
  pull_request:

env:
  IMAGE_NAME: pmmlserver

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

jobs:
  # Run tests.
  # See also https://docs.docker.com/docker-hub/builds/automated-testing/
  test:
    runs-on: ubuntu-latest

    steps:
      - name: Checkout source
        uses: actions/checkout@v4

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

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

      - name: Run tests
        uses: docker/build-push-action@v5
        with:
          platforms: linux/amd64, linux/arm64/v8
          context: python
          file: python/pmml.Dockerfile
          push: false
          # https://github.com/docker/buildx/issues/1533
          provenance: false

  # Push image to GitHub Packages.
  # See also https://docs.docker.com/docker-hub/builds/
  push:
    # Ensure test job passes before pushing image.
    needs: test

    runs-on: ubuntu-latest
    if: github.event_name == 'push'

    steps:
      - name: Checkout source
        uses: actions/checkout@v4

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

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

      - name: Login to DockerHub
        uses: docker/login-action@v3
        with:
          username: ${{ secrets.DOCKER_USER }}
          password: ${{ secrets.DOCKER_PASSWORD }}

      - name: Export version variable
        run: |
          IMAGE_ID=kserve/$IMAGE_NAME

          # Change all uppercase to lowercase
          IMAGE_ID=$(echo $IMAGE_ID | tr '[A-Z]' '[a-z]')

          # Strip git ref prefix from version
          VERSION=$(echo "${{ github.ref }}" | sed -e 's,.*/\(.*\),\1,')

          # Strip "v" prefix from tag name
          # [[ "${{ github.ref }}" == "refs/tags/"* ]] && VERSION=$(echo $VERSION | sed -e 's/^v//')

          # Use Docker `latest` tag convention
          [ "$VERSION" == "master" ] && VERSION=latest

          echo VERSION=$VERSION >> $GITHUB_ENV
          echo IMAGE_ID=$IMAGE_ID >> $GITHUB_ENV

      - name: Build and push
        uses: docker/build-push-action@v5
        with:
          platforms: linux/amd64, linux/arm64/v8
          context: python
          file: python/pmml.Dockerfile
          push: true
          tags: ${{ env.IMAGE_ID }}:${{ env.VERSION }}
          # https://github.com/docker/buildx/issues/1533
          provenance: false


Upload Python Package

name: Upload Python Package

on:
  release:
    types: [created]

  workflow_dispatch:

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

jobs:
  deploy:
    runs-on: ubuntu-latest

    steps:
      - name: Checkout source
        uses: actions/checkout@v4

      - name: Set up Python
        uses: actions/setup-python@v2
        with:
          python-version: "3.x"

      - name: Install Poetry and version plugin
        run: ./test/scripts/gh-actions/setup-poetry.sh

      - name: Build and publish
        env:
          POETRY_HTTP_BASIC_PYPI_USERNAME: ${{ secrets.PYPI_USERNAME }}
          POETRY_HTTP_BASIC_PYPI_PASSWORD: ${{ secrets.PYPI_PASSWORD }}
        run: |
          cd python/kserve
          poetry build
          poetry publish


Python package

name: Python package

on:
  push:
    branches: [master, release*]
  pull_request:
    branches: []
  workflow_dispatch:

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

jobs:
  lint:
    runs-on: ubuntu-latest
    strategy:
      matrix:
        python-version: ["3.11"]
    name: Lint
    steps:
      - name: Check out source repository
        uses: actions/checkout@v4
      - name: Set up Python environment ${{ matrix.python-version }}
        uses: actions/setup-python@v5
        with:
          python-version: ${{ matrix.python-version }}
      - name: Lint with flake8
        uses: py-actions/flake8@v2
        with:
          args: "--config .flake8"
          path: "."
      - name: Check formatting with black
        uses: psf/black@stable
        with:
          options: "--check --diff --config python/pyproject.toml"
          src: "."
          version: "~= 24.3"
  build:
    runs-on: ubuntu-latest
    strategy:
      matrix:
        python-version: ["3.8", "3.9", "3.10", "3.11"]
    steps:
      - name: Checkout source
        uses: actions/checkout@v4

      - name: Free-up disk space
        uses: ./.github/actions/free-up-disk-space

      - name: Set up Python ${{ matrix.python-version }}
        id: setup-python
        uses: actions/setup-python@v5
        with:
          python-version: ${{ matrix.python-version }}

      - name: Install Poetry and version plugin
        run: ./test/scripts/gh-actions/setup-poetry.sh

      - name: Configure Poetry cache
        run: |
          sudo mkdir -p /mnt/poetry
          # change permission so that poetry can install without sudo
          sudo chown -R $USER /mnt/poetry
          poetry config cache-dir /mnt/poetry

      # load poetry cache if cache exists
      - name: Load poetry cache
        id: cached-poetry-dependencies
        uses: actions/cache@v4
        with:
          path: /mnt/poetry
          key: poetry-${{ steps.setup-python.outputs.python-version }}-${{ hashFiles('**/poetry.lock') }}

      # ----------------------------------------Kserve Unit Tests--------------------------------------------------------
      # load cached kserve venv if cache exists
      - name: Load cached kserve venv
        id: cached-kserve-dependencies
        uses: actions/cache@v4
        with:
          path: python/kserve/.venv
          key: kserve-venv-${{ steps.setup-python.outputs.python-version }}-${{ hashFiles('**/kserve/poetry.lock') }}
      # install kserve dependencies if cache does not exist
      - name: Install kserve dependencies
        if: steps.cached-kserve-dependencies.outputs.cache-hit != 'true'
        run: |
          cd python/kserve
          make install_dependencies
      - name: Install kserve
        run: |
          cd python/kserve
          make dev_install
      - name: Test kserve
        run: |
          cd python
          source kserve/.venv/bin/activate
          pytest --cov=kserve ./kserve

      # ----------------------------------------Kserve Pydantic V1 Unit Tests--------------------------------------------
      - name: Setup kserve pydantic v1 directory
        run: |
          mkdir -p python/kserve-pydantic-v1
          cp -r python/kserve/* python/kserve-pydantic-v1
          cd python/kserve-pydantic-v1
          # update the lock file without installing dependencies
          poetry update "pydantic<2.0" --lock
      - name: Load cached kserve pydantic v1 venv
        id: cached-kserve-pydantic-v1-dependencies
        uses: actions/cache@v3
        with:
          path: python/kserve-pydantic-v1/.venv
          key: kserve-pydantic-v1-venv-${{ steps.setup-python.outputs.python-version }}-${{ hashFiles('**/kserve-pydantic-v1/poetry.lock') }}
      # install kserve pydantic v1 dependencies if cache does not exist
      - name: Install kserve pydantic v1 dependencies
        if: steps.cached-kserve-pydantic-v1-dependencies.outputs.cache-hit != 'true'
        run: |
          cd python/kserve-pydantic-v1
          make install_dependencies
      - name: Install kserve pydantic v1
        run: |
          cd python/kserve-pydantic-v1
          make dev_install
      - name: Test kserve pydantic v1
        run: |
          cd python
          source kserve-pydantic-v1/.venv/bin/activate
          pytest --cov=kserve ./kserve-pydantic-v1

      # ----------------------------------------Sklearn Server Unit Tests------------------------------------------------
      # load cached sklearn venv if cache exists
      - name: Load cached sklearn venv
        id: cached-sklearn-dependencies
        uses: actions/cache@v4
        with:
          path: python/sklearnserver/.venv
          key: sklearn-venv-${{ steps.setup-python.outputs.python-version }}-${{ hashFiles('**/kserve/poetry.lock', '**/sklearnserver/poetry.lock') }}
        # install sklearn server dependencies if cache does not exist
      - name: Install sklearn dependencies
        if: steps.cached-sklearn-dependencies.outputs.cache-hit != 'true'
        run: |
          cd python/sklearnserver
          make install_dependencies
      - name: Install sklearnserver
        run: |
          cd python/sklearnserver
          make dev_install
      - name: Test sklearnserver
        run: |
          cd python
          source sklearnserver/.venv/bin/activate
          pytest --cov=sklearnserver ./sklearnserver

      # ----------------------------------------Xgb Server Unit Tests------------------------------------------------
      # load cached xgb venv if cache exists
      - name: Load cached xgb venv
        id: cached-xgb-dependencies
        uses: actions/cache@v4
        with:
          path: python/xgbserver/.venv
          key: xgb-venv-${{ steps.setup-python.outputs.python-version }}-${{ hashFiles('**/kserve/poetry.lock', '**/xgbserver/poetry.lock') }}
        # install xgb server dependencies if cache does not exist
      - name: Install xgb dependencies
        if: steps.cached-xgb-dependencies.outputs.cache-hit != 'true'
        run: |
          cd python/xgbserver
          make install_dependencies
      - name: Install xgbserver
        run: |
          cd python/xgbserver
          make dev_install
      - name: Test xgbserver
        run: |
          cd python
          source xgbserver/.venv/bin/activate
          pytest --cov=xgbserver ./xgbserver

      # ----------------------------------------Pmml Server Unit Tests------------------------------------------------
      # load cached pmml venv if cache exists
      - name: Load cached pmml venv
        id: cached-pmml-dependencies
        uses: actions/cache@v4
        with:
          path: python/pmmlserver/.venv
          key: pmml-venv-${{ steps.setup-python.outputs.python-version }}-${{ hashFiles('**/kserve/poetry.lock', '**/pmmlserver/poetry.lock') }}
        # install pmml server dependencies if cache does not exist
      - name: Install pmml dependencies
        if: steps.cached-pmml-dependencies.outputs.cache-hit != 'true'
        run: |
          cd python/pmmlserver
          make install_dependencies
      - name: Install pmmlserver
        run: |
          cd python/pmmlserver
          make dev_install
      - name: Test pmmlserver
        run: |
          cd python
          source pmmlserver/.venv/bin/activate
          pytest --cov=pmmlserver ./pmmlserver

      # ----------------------------------------Lgb Server Unit Tests------------------------------------------------
      # load cached lgb venv if cache exists
      - name: Load cached lgb venv
        id: cached-lgb-dependencies
        uses: actions/cache@v4
        with:
          path: python/lgbserver/.venv
          key: lgb-venv-${{ steps.setup-python.outputs.python-version }}-${{ hashFiles('**/kserve/poetry.lock', '**/lgbserver/poetry.lock') }}
        # install lgb server dependencies if cache does not exist
      - name: Install lgb dependencies
        if: steps.cached-lgb-dependencies.outputs.cache-hit != 'true'
        run: |
          cd python/lgbserver
          make install_dependencies
      - name: Install lgbserver
        run: |
          cd python/lgbserver
          make dev_install
      - name: Test lgbserver
        run: |
          cd python
          source lgbserver/.venv/bin/activate
          pytest --cov=lgbserver ./lgbserver

      # ----------------------------------------Paddle Server Unit Tests------------------------------------------------
      # load cached paddle venv if cache exists
      - name: Load cached paddle venv
        id: cached-paddle-dependencies
        uses: actions/cache@v4
        with:
          path: python/paddleserver/.venv
          key: paddle-venv-${{ steps.setup-python.outputs.python-version }}-${{ hashFiles('**/kserve/poetry.lock', '**/paddleserver/poetry.lock') }}
        # install paddle server dependencies if cache does not exist
      - name: Install paddle dependencies
        if: steps.cached-paddle-dependencies.outputs.cache-hit != 'true'
        run: |
          echo "python version ${{ steps.setup-python.outputs.python-version }}"
          cd python/paddleserver
          make install_dependencies
      - name: Install paddleserver
        run: |
          cd python/paddleserver
          make dev_install
      - name: Test paddleserver
        run: |
          cd python
          source paddleserver/.venv/bin/activate
          pytest --cov=paddleserver ./paddleserver

      # ----------------------------------------Huggingface Server Unit Tests------------------------------------------------
      # load cached huggingface venv if cache exists
      - name: Load cached huggingface venv
        if: ${{ !startsWith(steps.setup-python.outputs.python-version, '3.8') }}
        id: huggingface-dependencies
        uses: actions/cache@v4
        with:
          path: /mnt/python/huggingfaceserver-venv
          key: huggingface-venv-${{ steps.setup-python.outputs.python-version }}-${{ hashFiles('**/kserve/poetry.lock', '**/huggingfaceserver/poetry.lock') }}
        # install huggingface server dependencies if cache does not exist
      - name: Configure poetry for huggingface server
        if: ${{ !startsWith(steps.setup-python.outputs.python-version, '3.8') }}
        run: |
          poetry config virtualenvs.path /mnt/python/huggingfaceserver-venv
          poetry config virtualenvs.in-project false
      - name: Install huggingface dependencies
        if: ${{ steps.cached-huggingface-dependencies.outputs.cache-hit != 'true' && !startsWith(steps.setup-python.outputs.python-version, '3.8') }}
        run: |
          sudo mkdir -p /mnt/python/huggingfaceserver-venv
          # change permission so that poetry can install without sudo
          sudo chown -R $USER /mnt/python/huggingfaceserver-venv
          cd python/huggingfaceserver
          make install_dependencies
      - name: Install huggingface server
        if: ${{ !startsWith(steps.setup-python.outputs.python-version, '3.8') }}
        run: |
          cd python/huggingfaceserver
          make dev_install
      - name: Test huggingfaceserver
        if: ${{ !startsWith(steps.setup-python.outputs.python-version, '3.8') }}
        run: |
          cd python/huggingfaceserver
          poetry run -- pytest --cov=huggingfaceserver -vv

      - name: Free space after tests
        run: |
          df -hT


Queue Proxy Extension Docker Publisher

name: Queue Proxy Extension Docker Publisher

on:
  push:
    # Publish `master` as Docker `latest` image.
    branches:
      - master

    # Publish `v1.2.3` tags as releases.
    tags:
      - v*

  # Run tests for any PRs.
  pull_request:

env:
  IMAGE_NAME: qpext

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

jobs:
  # Run tests.
  # See also https://docs.docker.com/docker-hub/builds/automated-testing/
  test:
    runs-on: ubuntu-latest

    steps:
      - name: Checkout source
        uses: actions/checkout@v4

      - name: Run tests
        run: |
          if [ -f docker-compose.test.yml ]; then
            docker-compose --file docker-compose.test.yml build
            docker-compose --file docker-compose.test.yml run sut
          else
            docker buildx build . --file qpext/qpext.Dockerfile
          fi

  # Push image to GitHub Packages.
  # See also https://docs.docker.com/docker-hub/builds/
  push:
    # Ensure test job passes before pushing image.
    needs: test

    runs-on: ubuntu-latest
    if: github.event_name == 'push'

    steps:
      - name: Checkout source
        uses: actions/checkout@v4

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

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

      - name: Login to DockerHub
        uses: docker/login-action@v3
        with:
          username: ${{ secrets.DOCKER_USER }}
          password: ${{ secrets.DOCKER_PASSWORD }}

      - name: export version variable
        run: |
          IMAGE_ID=kserve/$IMAGE_NAME

          # Change all uppercase to lowercase
          IMAGE_ID=$(echo $IMAGE_ID | tr '[A-Z]' '[a-z]')

          # Strip git ref prefix from version
          VERSION=$(echo "${{ github.ref }}" | sed -e 's,.*/\(.*\),\1,')

          # Strip "v" prefix from tag name
          # [[ "${{ github.ref }}" == "refs/tags/"* ]] && VERSION=$(echo $VERSION | sed -e 's/^v//')

          # Use Docker `latest` tag convention
          [ "$VERSION" == "master" ] && VERSION=latest

          echo VERSION=$VERSION >> $GITHUB_ENV
          echo IMAGE_ID=$IMAGE_ID >> $GITHUB_ENV

      - name: Build and push
        uses: docker/build-push-action@v5
        with:
          platforms: linux/amd64,linux/arm/v7,linux/arm64/v8,linux/ppc64le,linux/s390x
          context: "."
          file: qpext/qpext.Dockerfile
          push: true
          tags: ${{ env.IMAGE_ID }}:${{ env.VERSION }}
          # https://github.com/docker/buildx/issues/1533
          provenance: false


Re-Run PR tests

name: Re-Run PR tests

on:
  issue_comment:
    types: [created]

jobs:
  rerun_pr_tests:
    name: rerun_pr_tests
    if: ${{ github.event.issue.pull_request }}
    runs-on: ubuntu-20.04
    steps:
    - uses: estroz/rerun-actions@main
      with:
        repo_token: ${{ secrets.GITHUB_TOKEN }}
        comment_id: ${{ github.event.comment.id }}


Router Docker Publisher

name: Router Docker Publisher

on:
  push:
    # Publish `master` as Docker `latest` image.
    branches:
      - master

    # Publish `v1.2.3` tags as releases.
    tags:
      - v*

  # Run tests for any PRs.
  pull_request:

env:
  IMAGE_NAME: router

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

jobs:
  # Run tests.
  # See also https://docs.docker.com/docker-hub/builds/automated-testing/
  test:
    runs-on: ubuntu-latest

    steps:
      - name: Checkout source
        uses: actions/checkout@v4

      - name: Run tests
        run: |
          if [ -f docker-compose.test.yml ]; then
            docker-compose --file docker-compose.test.yml build
            docker-compose --file docker-compose.test.yml run sut
          else
            docker buildx build . --file router.Dockerfile
          fi

  # Push image to GitHub Packages.
  # See also https://docs.docker.com/docker-hub/builds/
  push:
    # Ensure test job passes before pushing image.
    needs: test

    runs-on: ubuntu-latest
    if: github.event_name == 'push'

    steps:
      - name: Checkout source
        uses: actions/checkout@v4

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

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

      - name: Login to DockerHub
        uses: docker/login-action@v3
        with:
          username: ${{ secrets.DOCKER_USER }}
          password: ${{ secrets.DOCKER_PASSWORD }}

      - name: export version variable
        run: |
          IMAGE_ID=kserve/$IMAGE_NAME

          # Change all uppercase to lowercase
          IMAGE_ID=$(echo $IMAGE_ID | tr '[A-Z]' '[a-z]')

          # Strip git ref prefix from version
          VERSION=$(echo "${{ github.ref }}" | sed -e 's,.*/\(.*\),\1,')

          # Strip "v" prefix from tag name
          # [[ "${{ github.ref }}" == "refs/tags/"* ]] && VERSION=$(echo $VERSION | sed -e 's/^v//')

          # Use Docker `latest` tag convention
          [ "$VERSION" == "master" ] && VERSION=latest

          echo VERSION=$VERSION >> $GITHUB_ENV
          echo IMAGE_ID=$IMAGE_ID >> $GITHUB_ENV

      - name: Build and push
        uses: docker/build-push-action@v5
        with:
          platforms: linux/amd64,linux/arm/v7,linux/arm64/v8,linux/ppc64le,linux/s390x
          context: .
          file: router.Dockerfile
          push: true
          tags: ${{ env.IMAGE_ID }}:${{ env.VERSION }}


Go Security Scan

name: "Go Security Scan"

on:
  pull_request:
  schedule:
    # The scheduled workflow runs every Sunday at 00:00 UTC time.
    - cron: '0 0 * * 0'
  workflow_dispatch: { }

jobs:
  go-security-scan:
    runs-on: ubuntu-latest
    env:
      GO111MODULE: on
    steps:
      - name: Checkout
        uses: actions/checkout@v4

      - name: Run Gosec Security Scanner
        uses: securego/gosec@master
        with:
          args: '-no-fail -fmt=sarif -out=go-security-scan-results.sarif -exclude-dir=pkg/client -exclude-dir=pkg/clientv1alpha1 ./...'

      - name: Upload SARIF file to Github Code Scanning
        uses: github/codeql-action/upload-sarif@v2
        with:
          sarif_file: go-security-scan-results.sarif
          category: gosec-tool


Twice a week image scan

name: Twice a week image scan
# Temporarily adding on push for testing
on:
  schedule:
    - cron: "0 0 * * 0,3"
  workflow_dispatch: {}

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

jobs:
  base-image-scan:
    name: scan images
    runs-on: ubuntu-latest
    strategy:
      matrix:
        image:
          [
            { name: kserve-controller, file: Dockerfile },
            { name: agent, file: agent.Dockerfile },
            {
              name: storage-initializer,
              file: python/storage-initializer.Dockerfile,
            },
            { name: router, file: router.Dockerfile },
          ]

    steps:
      - name: Checkout
        uses: actions/checkout@v4

      - name: Security scan on docker image
        uses: snyk/actions/docker@master
        id: docker-image-scan
        continue-on-error: true
        env:
          SNYK_TOKEN: ${{ secrets.SNYK_TOKEN }}
        with:
          image: kserve/${{ matrix.image.name }}
          args: --severity-threshold=low
            --file=${{ matrix.image.file }}
            --sarif-file-output=./application/${{ matrix.image.name }}/docker.snyk.sarif
          sarif: false

      - name: Upload sarif file to Github Code Scanning
        if: always()
        continue-on-error: true #avoid fail the pipeline if the SARIF upload fails.
        uses: github/codeql-action/upload-sarif@v3
        with:
          sarif_file: application/${{ matrix.image.name }}/docker.snyk.sarif

  predictor-image-scan:
    name: scan predictor images
    runs-on: ubuntu-latest
    strategy:
      matrix:
        image:
          [
            { name: sklearnserver, file: python/sklearn.Dockerfile },
            { name: xgbserver, file: python/xgb.Dockerfile },
            { name: pmmlserver, file: python/pmml.Dockerfile },
            { name: paddleserver, file: python/paddle.Dockerfile },
          ]

    steps:
      - name: Checkout
        uses: actions/checkout@v4

      - name: Security scan on docker image
        uses: snyk/actions/docker@master
        id: docker-image-scan
        continue-on-error: true
        env:
          SNYK_TOKEN: ${{ secrets.SNYK_TOKEN }}
        with:
          image: kserve/${{ matrix.image.name }}
          args: --severity-threshold=low
            --file=${{ matrix.image.file }}
            --sarif-file-output=./application/${{ matrix.image.name }}/docker.snyk.sarif
          sarif: false

      - name: Upload sarif file to Github Code Scanning
        if: always()
        uses: github/codeql-action/upload-sarif@v2
        with:
          sarif_file: application/${{ matrix.image.name }}/docker.snyk.sarif

  explainer-image-scan:
    name: scan explainer images
    runs-on: ubuntu-latest
    strategy:
      matrix:
        image:
          [
            { name: art-explainer, file: python/artexplainer.Dockerfile },
          ]

    steps:
      - name: Checkout
        uses: actions/checkout@v4

      - name: Security scan on docker image
        uses: snyk/actions/docker@master
        id: docker-image-scan
        continue-on-error: true
        env:
          SNYK_TOKEN: ${{ secrets.SNYK_TOKEN }}
        with:
          image: kserve/${{ matrix.image.name }}
          args: --severity-threshold=low
            --file=${{ matrix.image.file }}
            --sarif-file-output=./application/${{ matrix.image.name }}/docker.snyk.sarif
          sarif: false

      - name: Upload sarif file to Github Code Scanning
        if: always()
        uses: github/codeql-action/upload-sarif@v2
        with:
          sarif_file: application/${{ matrix.image.name }}/docker.snyk.sarif


Sklearn Server Docker Publisher

name: Sklearn Server Docker Publisher

on:
  push:
    # Publish `master` as Docker `latest` image.
    branches:
      - master

    # Publish `v1.2.3` tags as releases.
    tags:
      - v*

  # Run tests for any PRs.
  pull_request:

env:
  IMAGE_NAME: sklearnserver

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

jobs:
  # Run tests.
  # See also https://docs.docker.com/docker-hub/builds/automated-testing/
  test:
    runs-on: ubuntu-latest

    steps:
      - name: Checkout source
        uses: actions/checkout@v4

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

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

      - name: Run tests
        uses: docker/build-push-action@v5
        with:
          platforms: linux/amd64, linux/arm64/v8
          context: python
          file: python/sklearn.Dockerfile
          push: false
          # https://github.com/docker/buildx/issues/1533
          provenance: false

  # Push image to GitHub Packages.
  # See also https://docs.docker.com/docker-hub/builds/
  push:
    # Ensure test job passes before pushing image.
    needs: test

    runs-on: ubuntu-latest
    if: github.event_name == 'push'

    steps:
      - name: Checkout source
        uses: actions/checkout@v4

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

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

      - name: Login to DockerHub
        uses: docker/login-action@v3
        with:
          username: ${{ secrets.DOCKER_USER }}
          password: ${{ secrets.DOCKER_PASSWORD }}

      - name: Export version variable
        run: |
          IMAGE_ID=kserve/$IMAGE_NAME

          # Change all uppercase to lowercase
          IMAGE_ID=$(echo $IMAGE_ID | tr '[A-Z]' '[a-z]')

          # Strip git ref prefix from version
          VERSION=$(echo "${{ github.ref }}" | sed -e 's,.*/\(.*\),\1,')

          # Strip "v" prefix from tag name
          # [[ "${{ github.ref }}" == "refs/tags/"* ]] && VERSION=$(echo $VERSION | sed -e 's/^v//')

          # Use Docker `latest` tag convention
          [ "$VERSION" == "master" ] && VERSION=latest

          echo VERSION=$VERSION >> $GITHUB_ENV
          echo IMAGE_ID=$IMAGE_ID >> $GITHUB_ENV

      - name: Build and push
        uses: docker/build-push-action@v5
        with:
          platforms: linux/amd64, linux/arm64/v8
          context: python
          file: python/sklearn.Dockerfile
          push: true
          tags: ${{ env.IMAGE_ID }}:${{ env.VERSION }}
          # https://github.com/docker/buildx/issues/1533
          provenance: false


Storage Intializer Docker Publisher

name: Storage Intializer Docker Publisher

on:
  push:
    # Publish `master` as Docker `latest` image.
    branches:
      - master

    # Publish `v1.2.3` tags as releases.
    tags:
      - v*

  # Run tests for any PRs.
  pull_request:

env:
  IMAGE_NAME: storage-initializer

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

jobs:
  # Run tests.
  # See also https://docs.docker.com/docker-hub/builds/automated-testing/
  test:
    runs-on: ubuntu-latest

    steps:
      - name: Checkout source
        uses: actions/checkout@v4

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

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

      - name: Run tests
        uses: docker/build-push-action@v5
        with:
          platforms: linux/amd64, linux/arm64/v8
          context: python
          file: python/storage-initializer.Dockerfile
          push: false
          # https://github.com/docker/buildx/issues/1533
          provenance: false

  # Push image to GitHub Packages.
  # See also https://docs.docker.com/docker-hub/builds/
  push:
    # Ensure test job passes before pushing image.
    needs: test

    runs-on: ubuntu-latest
    if: github.event_name == 'push'

    steps:
      - name: Checkout source
        uses: actions/checkout@v4

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

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

      - name: Login to DockerHub
        uses: docker/login-action@v3
        with:
          username: ${{ secrets.DOCKER_USER }}
          password: ${{ secrets.DOCKER_PASSWORD }}

      - name: Export version variable
        run: |
          IMAGE_ID=kserve/$IMAGE_NAME

          # Change all uppercase to lowercase
          IMAGE_ID=$(echo $IMAGE_ID | tr '[A-Z]' '[a-z]')

          # Strip git ref prefix from version
          VERSION=$(echo "${{ github.ref }}" | sed -e 's,.*/\(.*\),\1,')

          # Strip "v" prefix from tag name
          # [[ "${{ github.ref }}" == "refs/tags/"* ]] && VERSION=$(echo $VERSION | sed -e 's/^v//')

          # Use Docker `latest` tag convention
          [ "$VERSION" == "master" ] && VERSION=latest

          echo VERSION=$VERSION >> $GITHUB_ENV
          echo IMAGE_ID=$IMAGE_ID >> $GITHUB_ENV

      - name: Build and push
        uses: docker/build-push-action@v5
        with:
          platforms: linux/amd64, linux/arm64/v8
          context: python
          file: python/storage-initializer.Dockerfile
          push: true
          tags: ${{ env.IMAGE_ID }}:${{ env.VERSION }}
          # https://github.com/docker/buildx/issues/1533
          provenance: false


Tf2Openapi Docker Publisher

name: Tf2Openapi Docker Publisher

on:
  push:
    # Publish `master` as Docker `latest` image.
    branches:
      - master

    # Publish `v1.2.3` tags as releases.
    tags:
      - v*

  # Run tests for any PRs.
  pull_request:

env:
  IMAGE_NAME: tf2openapi

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

jobs:
  # Run tests.
  # See also https://docs.docker.com/docker-hub/builds/automated-testing/
  test:
    runs-on: ubuntu-latest

    steps:
      - name: Checkout source
        uses: actions/checkout@v4

      - name: Run tests
        run: |
          if [ -f docker-compose.test.yml ]; then
            docker-compose --file docker-compose.test.yml build
            docker-compose --file docker-compose.test.yml run sut
          else
            docker buildx build . --file tools/tf2openapi/Dockerfile
          fi

  # Push image to GitHub Packages.
  # See also https://docs.docker.com/docker-hub/builds/
  push:
    # Ensure test job passes before pushing image.
    needs: test

    runs-on: ubuntu-latest
    if: github.event_name == 'push'

    steps:
      - name: Checkout source
        uses: actions/checkout@v4

      - name: Build image
        run: |
          docker buildx build . --file tools/tf2openapi/Dockerfile --tag $IMAGE_NAME

      - name: Log into registry
        run: docker login -u ${{ secrets.DOCKER_USER }} -p ${{ secrets.DOCKER_PASSWORD }}

      - name: Push image
        run: |
          IMAGE_ID=kserve/$IMAGE_NAME

          # Change all uppercase to lowercase
          IMAGE_ID=$(echo $IMAGE_ID | tr '[A-Z]' '[a-z]')

          # Strip git ref prefix from version
          VERSION=$(echo "${{ github.ref }}" | sed -e 's,.*/\(.*\),\1,')

          # Strip "v" prefix from tag name
          # [[ "${{ github.ref }}" == "refs/tags/"* ]] && VERSION=$(echo $VERSION | sed -e 's/^v//')

          # Use Docker `latest` tag convention
          [ "$VERSION" == "master" ] && VERSION=latest

          echo IMAGE_ID=$IMAGE_ID
          echo VERSION=$VERSION

          docker tag $IMAGE_NAME $IMAGE_ID:$VERSION
          docker push $IMAGE_ID:$VERSION


Transformer Docker Publisher

name: Transformer Docker Publisher

on:
  push:
    # Publish `master` as Docker `latest` image.
    branches:
      - master

  # Run tests for any PRs.
  pull_request:

env:
  IMAGE_NAME: image-transformer
  GRPC_IMAGE_NAME: custom-image-transformer-grpc

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

jobs:
  # Run tests.
  # See also https://docs.docker.com/docker-hub/builds/automated-testing/
  test:
    runs-on: ubuntu-latest

    steps:
      - name: Checkout source
        uses: actions/checkout@v4

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

      - name: Run tests
        uses: docker/build-push-action@v5
        with:
          platforms: linux/amd64
          context: python
          file: python/custom_transformer.Dockerfile
          push: false
          # https://github.com/docker/buildx/issues/1533
          provenance: false

  # Push image to GitHub Packages.
  # See also https://docs.docker.com/docker-hub/builds/
  push:
    # Ensure test job passes before pushing image.
    needs: test

    runs-on: ubuntu-latest
    if: github.event_name == 'push'

    steps:
      - name: Checkout source
        uses: actions/checkout@v4

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

      - name: Login to DockerHub
        uses: docker/login-action@v3
        with:
          username: ${{ secrets.DOCKER_USER }}
          password: ${{ secrets.DOCKER_PASSWORD }}

      - name: Export version variable
        run: |
          IMAGE_ID=kserve/$IMAGE_NAME

          # Change all uppercase to lowercase
          IMAGE_ID=$(echo $IMAGE_ID | tr '[A-Z]' '[a-z]')

          # Strip git ref prefix from version
          VERSION=$(echo "${{ github.ref }}" | sed -e 's,.*/\(.*\),\1,')

          # Strip "v" prefix from tag name
          # [[ "${{ github.ref }}" == "refs/tags/"* ]] && VERSION=$(echo $VERSION | sed -e 's/^v//')

          # Use Docker `latest` tag convention
          [ "$VERSION" == "master" ] && VERSION=latest

          echo VERSION=$VERSION >> $GITHUB_ENV
          echo IMAGE_ID=$IMAGE_ID >> $GITHUB_ENV

      - name: Build and push
        uses: docker/build-push-action@v5
        with:
          platforms: linux/amd64
          context: python
          file: python/custom_transformer.Dockerfile
          push: true
          tags: ${{ env.IMAGE_ID }}:${{ env.VERSION }}
          # https://github.com/docker/buildx/issues/1533
          provenance: false

  # Run tests.
  # See also https://docs.docker.com/docker-hub/builds/automated-testing/
  test-transformer-grpc:
    runs-on: ubuntu-latest

    steps:
      - name: Checkout source
        uses: actions/checkout@v4

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

      - name: Run tests
        uses: docker/build-push-action@v5
        with:
          platforms: linux/amd64
          context: python
          file: python/custom_transformer_grpc.Dockerfile
          push: false
          # https://github.com/docker/buildx/issues/1533
          provenance: false

  # Push image to GitHub Packages.
  # See also https://docs.docker.com/docker-hub/builds/
  push-transformer-grpc:
    # Ensure test job passes before pushing image.
    needs: test

    runs-on: ubuntu-latest
    if: github.event_name == 'push'

    steps:
      - name: Checkout source
        uses: actions/checkout@v4

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

      - name: Login to DockerHub
        uses: docker/login-action@v3
        with:
          username: ${{ secrets.DOCKER_USER }}
          password: ${{ secrets.DOCKER_PASSWORD }}

      - name: Export version variable
        run: |
          IMAGE_ID=kserve/$GRPC_IMAGE_NAME

          # Change all uppercase to lowercase
          IMAGE_ID=$(echo $IMAGE_ID | tr '[A-Z]' '[a-z]')

          # Strip git ref prefix from version
          VERSION=$(echo "${{ github.ref }}" | sed -e 's,.*/\(.*\),\1,')

          # Strip "v" prefix from tag name
          # [[ "${{ github.ref }}" == "refs/tags/"* ]] && VERSION=$(echo $VERSION | sed -e 's/^v//')

          # Use Docker `latest` tag convention
          [ "$VERSION" == "master" ] && VERSION=latest

          echo VERSION=$VERSION >> $GITHUB_ENV
          echo IMAGE_ID=$IMAGE_ID >> $GITHUB_ENV

      - name: Build and push
        uses: docker/build-push-action@v5
        with:
          platforms: linux/amd64
          context: python
          file: python/custom_transformer_grpc.Dockerfile
          push: true
          tags: ${{ env.IMAGE_ID }}:${{ env.VERSION }}
          # https://github.com/docker/buildx/issues/1533
          provenance: false


Verify Generated Code

name: "Verify Generated Code"

on:
  pull_request:

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

jobs:
  verify-codegen:
    runs-on: ubuntu-latest
    steps:
      - name: Checkout source code
        uses: actions/checkout@v4

      - name: Setup Go
        uses: actions/setup-go@v5
        with:
          go-version: 1.21

      - name: Install dependencies
        run: |
          go mod download

      - name: Update Codegen
        shell: bash
        run: |
          GOPATH=$(go env GOPATH)
          KSERVE_PATH=$GOPATH/src/github.com/kserve/kserve
          echo "KSERVE_PATH=$KSERVE_PATH" >> "$GITHUB_ENV"
          mkdir -p $KSERVE_PATH
          cp -a . $KSERVE_PATH
          cd $KSERVE_PATH
          make generate
          make manifests

      - name: Verify
        shell: bash
        run: |
          cd $KSERVE_PATH

          # From: https://backreference.org/2009/12/23/how-to-match-newlines-in-sed/
          # This is to leverage this workaround:
          # https://github.com/actions/toolkit/issues/193#issuecomment-605394935
          urlencode() {
            sed ':begin;$!N;s/\n/%0A/;tbegin'
          }

          # When running make generate, it introduces some lint errors which is fixed manually.
          # Reset these files to avoid false triggers due to those changes.
          git checkout -- python/kserve/test/__init__.py python/kserve/kserve/api_client.py

          if [ -z "$(git status --porcelain ./pkg ./python ./config ./charts)" ]; then
              echo "${{ github.repository }} up to date."
          else
              echo "Found diffs in: $(git diff-index --name-only HEAD -- ./pkg ./python ./charts)"
              for x in $(git diff-index --name-only HEAD -- ./pkg ./python ./charts); do
                  echo "::error file=$x::Please run make generate.%0A$(git diff $x | urlencode)"
              done
              echo "${{ github.repository }} is out of date. Please run make generate"
              exit 1
          fi


Xgbserver Server Docker Publisher

name: Xgbserver Server Docker Publisher

on:
  push:
    # Publish `master` as Docker `latest` image.
    branches:
      - master

    # Publish `v1.2.3` tags as releases.
    tags:
      - v*

  # Run tests for any PRs.
  pull_request:

env:
  IMAGE_NAME: xgbserver

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

jobs:
  # Run tests.
  # See also https://docs.docker.com/docker-hub/builds/automated-testing/
  test:
    runs-on: ubuntu-latest

    steps:
      - name: Checkout source code
        uses: actions/checkout@v4

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

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

      - name: Run tests
        uses: docker/build-push-action@v5
        with:
          platforms: linux/amd64, linux/arm64/v8
          context: python
          file: python/xgb.Dockerfile
          push: false
          # https://github.com/docker/buildx/issues/1533
          provenance: false

  # Push image to GitHub Packages.
  # See also https://docs.docker.com/docker-hub/builds/
  push:
    # Ensure test job passes before pushing image.
    needs: test

    runs-on: ubuntu-latest
    if: github.event_name == 'push'

    steps:
      - name: Checkout source code
        uses: actions/checkout@v4

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

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

      - name: Login to DockerHub
        uses: docker/login-action@v3
        with:
          username: ${{ secrets.DOCKER_USER }}
          password: ${{ secrets.DOCKER_PASSWORD }}

      - name: Export version variable
        run: |
          IMAGE_ID=kserve/$IMAGE_NAME

          # Change all uppercase to lowercase
          IMAGE_ID=$(echo $IMAGE_ID | tr '[A-Z]' '[a-z]')

          # Strip git ref prefix from version
          VERSION=$(echo "${{ github.ref }}" | sed -e 's,.*/\(.*\),\1,')

          # Strip "v" prefix from tag name
          # [[ "${{ github.ref }}" == "refs/tags/"* ]] && VERSION=$(echo $VERSION | sed -e 's/^v//')

          # Use Docker `latest` tag convention
          [ "$VERSION" == "master" ] && VERSION=latest

          echo VERSION=$VERSION >> $GITHUB_ENV
          echo IMAGE_ID=$IMAGE_ID >> $GITHUB_ENV

      - name: Build and push
        uses: docker/build-push-action@v5
        with:
          platforms: linux/amd64, linux/arm64/v8
          context: python
          file: python/xgb.Dockerfile
          push: true
          tags: ${{ env.IMAGE_ID }}:${{ env.VERSION }}
          # https://github.com/docker/buildx/issues/1533
          provenance: false


Build and Scan

---
name: Build and Scan
on:
  push:
    branches: [ main, master, dev, v*.* ]
  pull_request:
    branches: [ main, master, dev, v*.* ]

jobs:
  lint:
    runs-on: ubuntu-latest
    steps:
        - uses: actions/checkout@v3

        - name: Setup python
          uses: actions/setup-python@v4.1.0
          with:
              python-version: 3.11.7
              architecture: x64

        - name: Install linters
          run: pip install black pycodestyle pydocstyle djlint

        - name: Run black
          run: black . --check -l 200

        - name: Run pycodestyle
          run: pycodestyle --ignore E501,W605,W503,E203,E741 .

        - name: Run pydocstyle
          run: pydocstyle .

  pytest:
    runs-on: ubuntu-latest
    name: Run Tests
    steps:
      - uses: actions/checkout@v3

      - name: Setup python
        uses: actions/setup-python@v4.1.0
        with:
            python-version: 3.11.7
            architecture: x64

      - name: Install packages
        run: pip install -r requirements-dev.txt

      - name: Run pytest
        run:  pytest -n 4 -v --cov --cov-report xml:coverage.xml ${GITHUB_WORKSPACE}/tests

      - name: Get Cover
        uses: orgoro/coverage@v3.1
        with:
            coverageFile: ./coverage.xml
            token: ${{ secrets.GITHUB_TOKEN }}

  analyze:
    name: Analyze
    runs-on: ubuntu-latest
    permissions:
      actions: read
      contents: read
      security-events: write

    strategy:
      fail-fast: false
      matrix:
        language: [ 'javascript', 'python' ]

    steps:
    - name: Checkout repository
      uses: actions/checkout@v3

    - name: Initialize CodeQL
      uses: github/codeql-action/init@v2
      with:
        languages: ${{ matrix.language }}

    - name: Autobuild
      uses: github/codeql-action/autobuild@v2

    - name: Perform CodeQL Analysis
      uses: github/codeql-action/analyze@v2

  build:
    runs-on: macos-latest
    name: Build Desktop Apps
    steps:
        - uses: actions/checkout@v3

        - name: Setup python
          uses: actions/setup-python@v4.1.0
          with:
              python-version: 3.10.9
              architecture: x64

        - name: Update Brew
          if: ${{ github.event_name == 'push' }}
          run: brew update

        - name: Install Node
          if: ${{ github.event_name == 'push' }}
          run: brew install node

        - name: Install packages
          if: ${{ github.event_name == 'push' }}
          run: |
            npm install
            pip install -r requirements-dev.txt

        - name: Build pack
          if: ${{ github.event_name == 'push' }}
          run: |
            python3 ./tools/prepare_offline.py
            npm run distall

        - uses: actions/upload-artifact@v3
          with:
            name: dk64randomizer-setup.exe
            path: "${{ github.workspace }}/dist/dk64randomizer.exe"

        - uses: actions/upload-artifact@v3
          with:
            name: dk64randomizer.dmg
            path: "${{ github.workspace }}/dist/dk64randomizer.dmg"

        - uses: actions/upload-artifact@v3
          with:
            name: dk64randomizer.deb
            path: "${{ github.workspace }}/dist/dk64randomizer.deb"


Release to Github Pages Prod

---
name: Release to Github Pages Prod
on:
  push:
    branches: [ master ]
jobs:
  build-and-deploy:
    runs-on: ubuntu-latest
    steps:
    - uses: actions/checkout@v3

    - name: Setup python
      uses: actions/setup-python@v4.1.0
      with:
          python-version: 3.10.9
          architecture: x64

    - name: Install packages
      run: |
        pip install -r requirements-dev.txt
        pip install wheel setuptools

    - name: Build minified versions
      run: python3 ./tools/prepare_live.py

    - name: Remove Git Ignore (This might be changed in the future)
      run: rm .gitignore

    - name: Move Files
      run: mkdir ./deploy-directory && mv -f ./* ./deploy-directory/ || true

    - name: Pre Write Files
      run: echo 'This repo is for Github Pages for DK64Rando, you need to go to https://github.com/2dos/DK64-Randomizer' > ./deploy-directory/README.md && echo 'dk64randomizer.com' > ./deploy-directory/CNAME && touch ./deploy-directory/.nojekyll

    - name: Deploy to Github Pages
      uses: hpcodecraft/action-deploy-workspace-to-repo@v2.2
      env:
        GITHUB_ACCESS_TOKEN: ${{ secrets.ACCESS_TOKEN }}
        SRC_FOLDER: ./deploy-directory
        DEST_OWNER: 2dos
        DEST_REPO: DK64-Randomizer-Release
        DEST_BRANCH: main
        DEST_FOLDER: ./
        DEST_PREDEPLOY_CLEANUP: rm -rf ./*


Release to Github Pages

---
name: Release to Github Pages
on:
  push:
    branches: [ dev ]
jobs:
  build-and-deploy:
    runs-on: ubuntu-latest
    if: contains(github.actor, '[bot]')
    steps:
    - uses: actions/checkout@v3

    - name: Setup python
      uses: actions/setup-python@v4.1.0
      with:
          python-version: 3.10.9
          architecture: x64

    - name: Install packages
      run: |
        pip install -r requirements-dev.txt
        pip install wheel setuptools

    - name: Build minified versions
      run: python3 ./tools/prepare_live.py

    - name: Remove Git Ignore (This might be changed in the future)
      run: rm .gitignore

    - name: Move Files
      run: mkdir ./deploy-directory && mv -f ./* ./deploy-directory/ || true

    - name: Pre Write Files
      run: echo 'This repo Dev Github Pages for DK64Rando, you need to go to https://github.com/2dos/DK64-Randomizer' > ./deploy-directory/README.md && echo 'dev.dk64randomizer.com' > ./deploy-directory/CNAME && touch ./deploy-directory/.nojekyll

    - name: Deploy to Github Pages
      uses: hpcodecraft/action-deploy-workspace-to-repo@v2.2
      env:
        GITHUB_ACCESS_TOKEN: ${{ secrets.ACCESS_TOKEN }}
        SRC_FOLDER: ./deploy-directory
        DEST_OWNER: 2dos
        DEST_REPO: DK64-Randomizer-Dev
        DEST_BRANCH: main
        DEST_FOLDER: ./
        DEST_PREDEPLOY_CLEANUP: rm -rf ./*