name: Docker Push

on:
  workflow_dispatch:
    inputs:
      push:
        description: 'Push to Docker Hub'
        required: true
        default: 'false'
      tags:
        description: 'Custom tags to use for the push'
        required: false
        default: ''
  # # If we decide to build all images on every PR, we should make sure that
  # # they are NOT pushed to Docker Hub.
  # pull_request:
  #   paths-ignore:
  #     - '**/*.md'
  push:
    branches:
      - 'master'
      - 'staging'
      - 'bifrost-*'
    tags:
      - 'v*'

permissions:
  contents: read  #  to fetch code (actions/checkout)

jobs:
  docker-hub:
    if: github.repository == 'ipfs/kubo' || github.event_name == 'workflow_dispatch'
    name: Push Docker image to Docker Hub
    runs-on: ubuntu-latest
    timeout-minutes: 15
    env:
      IMAGE_NAME: ipfs/kubo
      LEGACY_IMAGE_NAME: ipfs/go-ipfs
    steps:
      - name: Check out the repo
        uses: actions/checkout@v4

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

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

      - name: Cache Docker layers
        uses: actions/cache@v4
        with:
          path: /tmp/.buildx-cache
          key: ${{ runner.os }}-buildx-${{ github.sha }}
          restore-keys: |
            ${{ runner.os }}-buildx-

      - name: Get tags
        id: tags
        if: github.event.inputs.tags == ''
        run: |
          echo "value<<EOF" >> $GITHUB_OUTPUT
          ./bin/get-docker-tags.sh "$(date -u +%F)" >> $GITHUB_OUTPUT
          echo "EOF" >> $GITHUB_OUTPUT
        shell: bash

      - name: Log in to Docker Hub
        uses: docker/login-action@v3
        with:
          username: ${{ vars.DOCKER_USERNAME }}
          password: ${{ secrets.DOCKER_PASSWORD }}

      # We have to build each platform separately because when using multi-arch
      # builds, only one platform is being loaded into the cache. This would
      # prevent us from testing the other platforms.
      - name: Build Docker image (linux/amd64)
        uses: docker/build-push-action@v6
        with:
          platforms: linux/amd64
          context: .
          push: false
          load: true
          file: ./Dockerfile
          tags: ${{ env.IMAGE_NAME }}:linux-amd64
          cache-from: type=local,src=/tmp/.buildx-cache
          cache-to: type=local,dest=/tmp/.buildx-cache-new

      - name: Build Docker image (linux/arm/v7)
        uses: docker/build-push-action@v6
        with:
          platforms: linux/arm/v7
          context: .
          push: false
          load: true
          file: ./Dockerfile
          tags: ${{ env.IMAGE_NAME }}:linux-arm-v7
          cache-from: type=local,src=/tmp/.buildx-cache
          cache-to: type=local,dest=/tmp/.buildx-cache-new

      - name: Build Docker image (linux/arm64/v8)
        uses: docker/build-push-action@v6
        with:
          platforms: linux/arm64/v8
          context: .
          push: false
          load: true
          file: ./Dockerfile
          tags: ${{ env.IMAGE_NAME }}:linux-arm64-v8
          cache-from: type=local,src=/tmp/.buildx-cache
          cache-to: type=local,dest=/tmp/.buildx-cache-new

      # We test all the images on amd64 host here. This uses QEMU to emulate
      # the other platforms.
      # NOTE: --version should finish instantly, but sometimes
      # it hangs on github CI (could be qemu issue), so we retry to remove false negatives
      - name: Smoke-test linux-amd64
        run: for i in {1..3}; do timeout 15s docker run --rm $IMAGE_NAME:linux-amd64 version --all && break || [ $i = 3 ] && exit 1; done
        timeout-minutes: 1
      - name: Smoke-test linux-arm-v7
        run: for i in {1..3}; do timeout 15s docker run --rm $IMAGE_NAME:linux-arm-v7 version --all && break || [ $i = 3 ] && exit 1; done
        timeout-minutes: 1
      - name: Smoke-test linux-arm64-v8
        run: for i in {1..3}; do timeout 15s docker run --rm $IMAGE_NAME:linux-arm64-v8 version --all && break || [ $i = 3 ] && exit 1; done
        timeout-minutes: 1

      # This will only push the previously built images.
      - if: github.event_name != 'workflow_dispatch' || github.event.inputs.push == 'true'
        name: Publish to Docker Hub
        uses: docker/build-push-action@v6
        with:
          platforms: linux/amd64,linux/arm/v7,linux/arm64/v8
          context: .
          push: true
          file: ./Dockerfile
          tags: "${{ github.event.inputs.tags || steps.tags.outputs.value }}"
          cache-from: type=local,src=/tmp/.buildx-cache-new
          cache-to: type=local,dest=/tmp/.buildx-cache-new

      # https://github.com/docker/build-push-action/issues/252
      # https://github.com/moby/buildkit/issues/1896
      - name: Move cache to limit growth
        run: |
          rm -rf /tmp/.buildx-cache
          mv /tmp/.buildx-cache-new /tmp/.buildx-cache
