name: "Push containers to Docker Hub on release"

on:
  push:
    tags:
      - '*.*.*'
  workflow_dispatch:
    inputs:
      # NO INPUTS

jobs:
  build:
    strategy:
      matrix:
        platform: [
          { platform: linux/amd64, cache: docker-release-amd64, artifactSuffix: amd64 },
          { platform: linux/arm64, cache: docker-release-arm64, artifactSuffix: arm64 },
        ]
    runs-on: ubuntu-latest
    steps:
      - name: Checkout
        uses: actions/checkout@v4

      - name: Setup environment
        run: cp .env.example .env

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

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

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

      - name: Build and push the backend container by digest
        id: backend-build
        uses: docker/build-push-action@v4
        with:
          context: .
          file: ./prod.Dockerfile
          target: backend
          cache-from: type=gha,timeout=200m,scope=${{ matrix.platform.cache }}
          cache-to: type=gha,mode=max,timeout=200m,scope=${{ matrix.platform.cache }}
          platforms: |
            ${{ matrix.platform.platform }}
          tags: |
            ${{ secrets.DOCKER_ORG_NAME }}/${{ secrets.DOCKER_BACKEND_CONTAINER_NAME }}
          outputs: type=image,push-by-digest=true,name-canonical=true,push=true

      - name: Build and push the frontend container by digest
        id: frontend-build
        uses: docker/build-push-action@v4
        with:
          context: .
          file: ./prod.Dockerfile
          target: app
          cache-from: type=gha,timeout=200m,scope=${{ matrix.platform.cache }}
          cache-to: type=gha,mode=max,timeout=200m,scope=${{ matrix.platform.cache }}
          platforms: |
            ${{ matrix.platform.platform }}
          tags: |
            ${{ secrets.DOCKER_ORG_NAME }}/${{ secrets.DOCKER_FRONTEND_CONTAINER_NAME }}
          outputs: type=image,push-by-digest=true,name-canonical=true,push=true

      - name: Build and push the admin dashboard container by digest
        id: sh_admin-build
        uses: docker/build-push-action@v4
        with:
          context: .
          file: ./prod.Dockerfile
          target: sh_admin
          cache-from: type=gha,timeout=200m,scope=${{ matrix.platform.cache }}
          cache-to: type=gha,mode=max,timeout=200m,scope=${{ matrix.platform.cache }}
          platforms: |
            ${{ matrix.platform.platform }}
          tags: |
            ${{ secrets.DOCKER_ORG_NAME }}/${{ secrets.DOCKER_SH_ADMIN_CONTAINER_NAME }}
          outputs: type=image,push-by-digest=true,name-canonical=true,push=true

      - name: Build and push the AIO container by digest
        id: aio-build
        uses: docker/build-push-action@v4
        with:
          context: .
          file: ./prod.Dockerfile
          target: aio
          cache-from: type=gha,timeout=200m,scope=${{ matrix.platform.cache }}
          cache-to: type=gha,mode=max,timeout=200m,scope=${{ matrix.platform.cache }}
          platforms: |
            ${{ matrix.platform.platform }}
          tags: |
            ${{ secrets.DOCKER_ORG_NAME }}/${{ secrets.DOCKER_AIO_CONTAINER_NAME }}
          outputs: type=image,push-by-digest=true,name-canonical=true,push=true

      - name: Make digest files
        run: |
          backend_digest="${{ steps.backend-build.outputs.digest }}"
          frontend_digest="${{ steps.frontend-build.outputs.digest }}"
          sh_admin_digest="${{ steps.sh_admin-build.outputs.digest }}"
          aio_digest="${{ steps.aio-build.outputs.digest }}"

          mkdir -p digests/backend digests/frontend digests/sh_admin digests/aio

          touch "digests/backend/${backend_digest#sha256:}"
          touch "digests/frontend/${frontend_digest#sha256:}"
          touch "digests/sh_admin/${sh_admin_digest#sha256:}"
          touch "digests/aio/${aio_digest#sha256:}"

      - name: Upload digests files as artifacts
        uses: actions/upload-artifact@v4
        with:
          name: release-docker-build-digests-${{ github.ref_name }}-${{ matrix.platform.artifactSuffix }}
          path: digests/*
          if-no-files-found: error
          retention-days: 1

  assemble-and-push-to-docker-hub:
    runs-on: ubuntu-latest
    needs:
      - build
    steps:
      - name: Download digests from artifacts
        uses: actions/download-artifact@v4
        with:
          path: digests
          pattern: release-docker-build-digests-${{ github.ref_name }}-*
          merge-multiple: true

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

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

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

      - name: "[Backend] - Create manifest list and push"
        working-directory: digests/backend
        run: |
          docker buildx imagetools create -t ${{ secrets.DOCKER_ORG_NAME }}/${{ secrets.DOCKER_BACKEND_CONTAINER_NAME }}:${{ github.ref_name }} \
            $(printf '${{ secrets.DOCKER_ORG_NAME }}/${{ secrets.DOCKER_BACKEND_CONTAINER_NAME }}@sha256:%s ' *)

          docker buildx imagetools create -t ${{ secrets.DOCKER_ORG_NAME }}/${{ secrets.DOCKER_BACKEND_CONTAINER_NAME }}:latest \
            $(printf '${{ secrets.DOCKER_ORG_NAME }}/${{ secrets.DOCKER_BACKEND_CONTAINER_NAME }}@sha256:%s ' *)


      - name: "[Frontend] - Create manifest list and push"
        working-directory: digests/frontend
        run: |
          docker buildx imagetools create -t ${{ secrets.DOCKER_ORG_NAME }}/${{ secrets.DOCKER_FRONTEND_CONTAINER_NAME }}:${{ github.ref_name }} \
            $(printf '${{ secrets.DOCKER_ORG_NAME }}/${{ secrets.DOCKER_FRONTEND_CONTAINER_NAME }}@sha256:%s ' *)

          docker buildx imagetools create -t ${{ secrets.DOCKER_ORG_NAME }}/${{ secrets.DOCKER_FRONTEND_CONTAINER_NAME }}:latest \
            $(printf '${{ secrets.DOCKER_ORG_NAME }}/${{ secrets.DOCKER_FRONTEND_CONTAINER_NAME }}@sha256:%s ' *)


      - name: "[SH Admin] - Create manifest list and push"
        working-directory: digests/sh_admin
        run: |
          docker buildx imagetools create -t ${{ secrets.DOCKER_ORG_NAME }}/${{ secrets.DOCKER_SH_ADMIN_CONTAINER_NAME }}:${{ github.ref_name }} \
            $(printf '${{ secrets.DOCKER_ORG_NAME }}/${{ secrets.DOCKER_SH_ADMIN_CONTAINER_NAME }}@sha256:%s ' *)

          docker buildx imagetools create -t ${{ secrets.DOCKER_ORG_NAME }}/${{ secrets.DOCKER_SH_ADMIN_CONTAINER_NAME }}:latest \
            $(printf '${{ secrets.DOCKER_ORG_NAME }}/${{ secrets.DOCKER_SH_ADMIN_CONTAINER_NAME }}@sha256:%s ' *)

      - name: "[AIO] - Create manifest list and push"
        working-directory: digests/aio
        run: |
          docker buildx imagetools create -t ${{ secrets.DOCKER_ORG_NAME }}/${{ secrets.DOCKER_AIO_CONTAINER_NAME }}:${{ github.ref_name }} \
            $(printf '${{ secrets.DOCKER_ORG_NAME }}/${{ secrets.DOCKER_AIO_CONTAINER_NAME }}@sha256:%s ' *)

          docker buildx imagetools create -t ${{ secrets.DOCKER_ORG_NAME }}/${{ secrets.DOCKER_AIO_CONTAINER_NAME }}:latest \
            $(printf '${{ secrets.DOCKER_ORG_NAME }}/${{ secrets.DOCKER_AIO_CONTAINER_NAME }}@sha256:%s ' *)

