name: Docker Build and Deploy

on:
  workflow_call:
    secrets:
      DOCKERHUB_USERNAME:
        required: true
      DOCKERHUB_TOKEN:
        required: true
      DISCORD_WEBHOOK:
        required: false
  workflow_dispatch:
    inputs:
      branch_name:
        description: 'Branch name to build Docker images for'
        required: false
        default: 'develop'
        type: string

concurrency:
  group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}
  cancel-in-progress: true

permissions:
  contents: read

env:
  IMAGE_NAME: "freqtradeorg/freqtrade"
  CACHE_IMAGE: "freqtradeorg/freqtrade_cache"
  GHCR_IMAGE_NAME: "ghcr.io/freqtrade/freqtrade"
  PI_PLATFORM: "linux/arm/v7"

jobs:
  deploy-docker:
    name: "Deploy Docker x64 and armv7l"
    runs-on: ubuntu-22.04
    if: github.repository == 'freqtrade/freqtrade'
    environment:
      name: docker

    steps:
    - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
      with:
        persist-credentials: false

    - name: Visualize disk usage before build
      run: df -h

    - name: Cleanup some disk space
      run: |
        docker system prune -a --force || true
        docker builder prune -af || true

    - name: Visualize disk usage after cleanup
      run: df -h

    - name: Set docker tag names
      id: tags
      uses: $/.github/actions/docker-tags

    - name: Login to Docker Hub
      uses: docker/login-action@dbcb813823bdd20940b903addbd779551569679f # v4.6.0
      with:
        username: ${{ secrets.DOCKERHUB_USERNAME }}
        password: ${{ secrets.DOCKERHUB_TOKEN }}

    - name: Set up QEMU
      uses: docker/setup-qemu-action@1f40c72289eff860ee54a304f1438e3cff362e0a # v4.3.0
      with:
        cache-image: false

    - name: Set up Docker Buildx
      id: buildx
      uses: docker/setup-buildx-action@37fe631027851001ddb9b187196cc803df7f5f0e #v4.3.0

    - name: Available platforms
      run: echo ${PLATFORMS}
      env:
        PLATFORMS: ${{ steps.buildx.outputs.platforms }}

    - name: Build image without cache
      if: github.event_name == 'schedule'
      env:
        TAG: ${{ steps.tags.outputs.TAG }}
      run: |
        docker build -t ${CACHE_IMAGE}:${TAG} .

    - name: Build ARMHF image without cache
      if: github.event_name == 'schedule'
      env:
        TAG_PI: ${{ steps.tags.outputs.TAG_PI }}
        CACHE_TAG_PI: ${{ steps.tags.outputs.CACHE_TAG_PI }}
      run: |
        docker buildx build \
          --cache-to=type=registry,ref=${CACHE_TAG_PI} \
          -f docker/Dockerfile.armhf \
          --platform ${PI_PLATFORM} \
          -t ${IMAGE_NAME}:${TAG_PI} \
          --push \
          --provenance=false \
          .

    - name: Build image with cache
      if: github.event_name != 'schedule'
      env:
        TAG: ${{ steps.tags.outputs.TAG }}
      run: |
        docker pull ${IMAGE_NAME}:${TAG} || true
        docker build --cache-from ${IMAGE_NAME}:${TAG} -t ${CACHE_IMAGE}:${TAG} .

    - name: Build ARMHF image with cache
      if: github.event_name != 'schedule'
      # disable provenance due to https://github.com/docker/buildx/issues/1509
      env:
        TAG_PI: ${{ steps.tags.outputs.TAG_PI }}
        CACHE_TAG_PI: ${{ steps.tags.outputs.CACHE_TAG_PI }}
      run: |
        docker buildx build \
          --cache-from=type=registry,ref=${CACHE_TAG_PI} \
          --cache-to=type=registry,ref=${CACHE_TAG_PI} \
          -f docker/Dockerfile.armhf \
          --platform ${PI_PLATFORM} \
          -t ${IMAGE_NAME}:${TAG_PI} \
          --push \
          --provenance=false \
          .

    - name: Run build for AI images
      env:
        TAG: ${{ steps.tags.outputs.TAG }}
        TAG_PLOT: ${{ steps.tags.outputs.TAG_PLOT }}
        TAG_FREQAI: ${{ steps.tags.outputs.TAG_FREQAI }}
        TAG_FREQAI_RL: ${{ steps.tags.outputs.TAG_FREQAI_RL }}
      run: |
        docker build --build-arg sourceimage=${CACHE_IMAGE} --build-arg sourcetag=${TAG} -t ${CACHE_IMAGE}:${TAG_PLOT} -f docker/Dockerfile.plot .
        docker build --build-arg sourceimage=${CACHE_IMAGE} --build-arg sourcetag=${TAG} -t ${CACHE_IMAGE}:${TAG_FREQAI} -f docker/Dockerfile.freqai .
        docker build --build-arg sourceimage=${CACHE_IMAGE} --build-arg sourcetag=${TAG_FREQAI} -t ${CACHE_IMAGE}:${TAG_FREQAI_RL} -f docker/Dockerfile.freqai_rl .


    - name: Run backtest in Docker
      env:
        TAG: ${{ steps.tags.outputs.TAG }}
      run: |
        docker run --rm -v $(pwd)/tests/testdata/config.tests.json:/freqtrade/config.json:ro -v $(pwd)/tests:/tests ${CACHE_IMAGE}:${TAG} backtesting --datadir /tests/testdata --strategy-path /tests/strategy/strats/ --strategy StrategyTestV3

    - name: Push cache images
      env:
        TAG: ${{ steps.tags.outputs.TAG }}
        TAG_PLOT: ${{ steps.tags.outputs.TAG_PLOT }}
        TAG_FREQAI: ${{ steps.tags.outputs.TAG_FREQAI }}
        TAG_FREQAI_RL: ${{ steps.tags.outputs.TAG_FREQAI_RL }}
      run: |
        docker push ${CACHE_IMAGE}:$TAG
        docker push ${CACHE_IMAGE}:$TAG_PLOT
        docker push ${CACHE_IMAGE}:$TAG_FREQAI
        docker push ${CACHE_IMAGE}:$TAG_FREQAI_RL

    - name: list Images
      run: |
        docker images

    - name: Visualize disk usage after build
      run: df -h

  deploy-arm:
    name: "Deploy Docker ARM64"
    permissions:
      packages: write # Needed to push package versions
    needs: [ deploy-docker ]
    # Must run on an ARM runner to avoid emulation
    runs-on: ubuntu-24.04-arm
    if: github.repository == 'freqtrade/freqtrade'
    environment:
      name: docker

    steps:
    - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
      with:
        persist-credentials: false

    - name: Set docker tag names
      id: tags
      uses: $/.github/actions/docker-tags

    - name: Login to Docker Hub
      uses: docker/login-action@dbcb813823bdd20940b903addbd779551569679f # v4.6.0
      with:
        username: ${{ secrets.DOCKERHUB_USERNAME }}
        password: ${{ secrets.DOCKERHUB_TOKEN }}

    - name: Login to github
      uses: docker/login-action@dbcb813823bdd20940b903addbd779551569679f # v4.6.0
      with:
        registry: ghcr.io
        username: ${{ github.actor }}
        password: ${{ secrets.GITHUB_TOKEN }}

    - name: Build image without cache
      if: github.event_name == 'schedule'
      env:
        TAG_ARM: ${{ steps.tags.outputs.TAG_ARM }}
      run: |
        docker build -t ${IMAGE_NAME}:${TAG_ARM} .

    - name: Build image with cache
      if: github.event_name != 'schedule'
      env:
        TAG_ARM: ${{ steps.tags.outputs.TAG_ARM }}
      run: |
        docker pull ${IMAGE_NAME}:${TAG_ARM} || true
        docker build --cache-from ${IMAGE_NAME}:${TAG_ARM} -t ${CACHE_IMAGE}:${TAG_ARM} .

    - name: Run build for AI images
      env:
        TAG_ARM: ${{ steps.tags.outputs.TAG_ARM }}
        TAG_PLOT_ARM: ${{ steps.tags.outputs.TAG_PLOT_ARM }}
        TAG_FREQAI_ARM: ${{ steps.tags.outputs.TAG_FREQAI_ARM }}
        TAG_FREQAI_RL_ARM: ${{ steps.tags.outputs.TAG_FREQAI_RL_ARM }}
      run: |
        docker build --build-arg sourceimage=${CACHE_IMAGE} --build-arg sourcetag=${TAG_ARM} -t ${CACHE_IMAGE}:${TAG_PLOT_ARM} -f docker/Dockerfile.plot .
        docker build --build-arg sourceimage=${CACHE_IMAGE} --build-arg sourcetag=${TAG_ARM} -t ${CACHE_IMAGE}:${TAG_FREQAI_ARM} -f docker/Dockerfile.freqai .
        docker build --build-arg sourceimage=${CACHE_IMAGE} --build-arg sourcetag=${TAG_FREQAI_ARM} -t ${CACHE_IMAGE}:${TAG_FREQAI_RL_ARM} -f docker/Dockerfile.freqai_rl .


    - name: Run backtest in Docker
      env:
        TAG_ARM: ${{ steps.tags.outputs.TAG_ARM }}
      run: |
        docker run --rm -v $(pwd)/tests/testdata/config.tests.json:/freqtrade/config.json:ro -v $(pwd)/tests:/tests ${CACHE_IMAGE}:${TAG_ARM} backtesting --datadir /tests/testdata --strategy-path /tests/strategy/strats/ --strategy StrategyTestV3

    - name: Docker images
      run: |
        docker images

    - name: Push cache images
      env:
        TAG_ARM: ${{ steps.tags.outputs.TAG_ARM }}
        TAG_PLOT_ARM: ${{ steps.tags.outputs.TAG_PLOT_ARM }}
        TAG_FREQAI_ARM: ${{ steps.tags.outputs.TAG_FREQAI_ARM }}
        TAG_FREQAI_RL_ARM: ${{ steps.tags.outputs.TAG_FREQAI_RL_ARM }}
      run: |
        docker push ${CACHE_IMAGE}:$TAG_PLOT_ARM
        docker push ${CACHE_IMAGE}:$TAG_FREQAI_ARM
        docker push ${CACHE_IMAGE}:$TAG_FREQAI_RL_ARM
        docker push ${CACHE_IMAGE}:$TAG_ARM

    - name: Create manifests
      env:
        TAG_ARM: ${{ steps.tags.outputs.TAG_ARM }}
        TAG: ${{ steps.tags.outputs.TAG }}
        TAG_PI: ${{ steps.tags.outputs.TAG_PI }}
      run: |
        docker buildx imagetools create \
          --tag ${IMAGE_NAME}:${TAG} \
          --tag ${GHCR_IMAGE_NAME}:${TAG} \
          ${CACHE_IMAGE}:${TAG} ${CACHE_IMAGE}:${TAG_ARM} ${IMAGE_NAME}:${TAG_PI}

    - name: Create multiarch image - Plot
      env:
        TAG_PLOT: ${{ steps.tags.outputs.TAG_PLOT }}
        TAG_PLOT_ARM: ${{ steps.tags.outputs.TAG_PLOT_ARM }}
      run: |
        docker buildx imagetools create \
          --tag ${IMAGE_NAME}:${TAG_PLOT} \
          --tag ${GHCR_IMAGE_NAME}:${TAG_PLOT} \
          ${CACHE_IMAGE}:${TAG_PLOT} ${CACHE_IMAGE}:${TAG_PLOT_ARM}

    - name: Create multiarch image - FreqAI
      env:
        TAG_FREQAI: ${{ steps.tags.outputs.TAG_FREQAI }}
        TAG_FREQAI_ARM: ${{ steps.tags.outputs.TAG_FREQAI_ARM }}
      run: |
        docker buildx imagetools create \
          --tag ${IMAGE_NAME}:${TAG_FREQAI} \
          --tag ${GHCR_IMAGE_NAME}:${TAG_FREQAI} \
          ${CACHE_IMAGE}:${TAG_FREQAI} ${CACHE_IMAGE}:${TAG_FREQAI_ARM}

    - name: Create multiarch image - FreqAI RL
      env:
        TAG_FREQAI_RL: ${{ steps.tags.outputs.TAG_FREQAI_RL }}
        TAG_FREQAI_RL_ARM: ${{ steps.tags.outputs.TAG_FREQAI_RL_ARM }}
        TAG_FREQAI_TORCH: ${{ steps.tags.outputs.TAG_FREQAI_TORCH }}
      run: |
        # Create special Torch tag - which is identical to the RL tag.
        docker buildx imagetools create \
          --tag ${IMAGE_NAME}:${TAG_FREQAI_RL} \
          --tag ${GHCR_IMAGE_NAME}:${TAG_FREQAI_RL} \
          --tag ${IMAGE_NAME}:${TAG_FREQAI_TORCH} \
          --tag ${GHCR_IMAGE_NAME}:${TAG_FREQAI_TORCH} \
          ${CACHE_IMAGE}:${TAG_FREQAI_RL} ${CACHE_IMAGE}:${TAG_FREQAI_RL_ARM}

    - name: Tag latest
      if: env.TAG == 'develop'
      env:
        TAG: ${{ steps.tags.outputs.TAG }}
      run: |
        # Tag image as latest
        docker buildx imagetools create \
          --tag ${GHCR_IMAGE_NAME}:${TAG} \
          --tag ${GHCR_IMAGE_NAME}:latest \
          --tag ${IMAGE_NAME}:latest \
          ${IMAGE_NAME}:${TAG}

    - name: Docker images
      run: |
        docker images

    - name: Image cleanup
      run: |
        docker image prune -a --force --filter "until=24h"

    - name: Discord notification
      uses: sarisia/actions-status-discord@eb045afee445dc055c18d3d90bd0f244fd062708 # v1.16.0
      if: always() && ( github.event_name != 'pull_request' || github.event.pull_request.head.repo.fork == false) && (github.event_name != 'schedule')
      with:
          title: Deploy Succeeded!
          webhook: ${{ secrets.DISCORD_WEBHOOK }}