name: docker

on:
    push:
        branches:
            - unstable
            - stable
        tags:
            - v*

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

env:
    DOCKER_PASSWORD: ${{ secrets.DOCKER_PASSWORD }}
    DOCKER_USERNAME: ${{ secrets.DOCKER_USERNAME }}
    # Enable self-hosted runners for the sigp repo only.
    SELF_HOSTED_RUNNERS: ${{ github.repository == 'sigp/lighthouse' }}

jobs:
    # Extract the VERSION which is either `latest` or `vX.Y.Z`, and the VERSION_SUFFIX
    # which is either empty or `-unstable`.
    #
    # It would be nice if the arch didn't get spliced into the version between `latest` and
    # `unstable`, but for now we keep the two parts of the version separate for backwards
    # compatibility.
    extract-version:
        runs-on: ubuntu-22.04
        steps:
            - name: Extract version (if stable)
              if: github.event.ref == 'refs/heads/stable'
              run: |
                    echo "VERSION=latest" >> $GITHUB_ENV
                    echo "VERSION_SUFFIX=" >> $GITHUB_ENV
            - name: Extract version (if unstable)
              if: github.event.ref == 'refs/heads/unstable'
              run: |
                    echo "VERSION=latest" >> $GITHUB_ENV
                    echo "VERSION_SUFFIX=-unstable" >> $GITHUB_ENV
            - name: Extract version (if tagged release)
              if: startsWith(github.event.ref, 'refs/tags')
              run: |
                    echo "VERSION=$(echo ${GITHUB_REF#refs/tags/})" >> $GITHUB_ENV
                    echo "VERSION_SUFFIX=" >> $GITHUB_ENV
        outputs:
            VERSION: ${{ env.VERSION }}
            VERSION_SUFFIX: ${{ env.VERSION_SUFFIX }}
    build-docker-single-arch:
        name: build-docker-${{ matrix.binary }}-${{ matrix.cpu_arch }}${{ matrix.features.version_suffix }}
        # Use self-hosted runners only on the sigp repo.
        runs-on: ${{ github.repository == 'sigp/lighthouse' && fromJson('["self-hosted", "linux", "release"]') || 'ubuntu-22.04'  }}
        strategy:
            matrix:
                binary:   [lighthouse,
                           lcli]
                cpu_arch: [aarch64,
                           x86_64]
                include:
                    - profile: maxperf

        needs: [extract-version]
        env:
            VERSION: ${{ needs.extract-version.outputs.VERSION }}
            VERSION_SUFFIX: ${{ needs.extract-version.outputs.VERSION_SUFFIX }}
        steps:
            - uses: actions/checkout@v4
            - name: Update Rust
              if: env.SELF_HOSTED_RUNNERS == 'false'
              run: rustup update stable
            - name: Dockerhub login
              run: |
                  echo "${DOCKER_PASSWORD}" | docker login --username ${DOCKER_USERNAME} --password-stdin

            - name: Sets env vars for Lighthouse
              if: startsWith(matrix.binary, 'lighthouse')
              run: |
                echo "CROSS_FEATURES=gnosis,spec-minimal,slasher-lmdb,jemalloc" >> $GITHUB_ENV

            - name: Set `make` command for lighthouse
              if: startsWith(matrix.binary, 'lighthouse')
              run: |
                echo "MAKE_CMD=build-${{ matrix.cpu_arch }}-portable" >> $GITHUB_ENV

            - name: Set `make` command for lcli
              if: startsWith(matrix.binary, 'lcli')
              run: |
                echo "MAKE_CMD=build-lcli-${{ matrix.cpu_arch }}" >> $GITHUB_ENV

            - name: Cross build binaries
              run: |
                  cargo install cross
                  env CROSS_PROFILE=${{ matrix.profile }} CROSS_FEATURES=${{ env.CROSS_FEATURES }} make ${{ env.MAKE_CMD }}

            - name: Make bin dir
              run: mkdir ./bin

            - name: Move cross-built binary into Docker scope
              run: mv ./target/${{ matrix.cpu_arch }}-unknown-linux-gnu/${{ matrix.profile }}/${{ matrix.binary }} ./bin

            - name: Map aarch64 to arm64 short arch
              if: startsWith(matrix.cpu_arch, 'aarch64')
              run: echo "SHORT_ARCH=arm64" >> $GITHUB_ENV

            - name: Map x86_64 to amd64 short arch
              if: startsWith(matrix.cpu_arch, 'x86_64')
              run: echo "SHORT_ARCH=amd64" >> $GITHUB_ENV;

            - name: Install QEMU
              if: env.SELF_HOSTED_RUNNERS == 'false'
              run: sudo apt-get update && sudo apt-get install -y qemu-user-static

            - name: Set up Docker Buildx
              if: env.SELF_HOSTED_RUNNERS == 'false'
              uses: docker/setup-buildx-action@v3

            - name: Build and push (Lighthouse)
              if: startsWith(matrix.binary, 'lighthouse')
              uses: docker/build-push-action@v5
              with:
                file: ./Dockerfile.cross
                context: .
                platforms: linux/${{ env.SHORT_ARCH }}
                push: true
                tags: |
                  ${{ github.repository_owner}}/${{ matrix.binary }}:${{ env.VERSION }}-${{ env.SHORT_ARCH }}${{ env.VERSION_SUFFIX }}
                  ${{ github.repository_owner}}/${{ matrix.binary }}:${{ env.VERSION }}-${{ env.SHORT_ARCH }}${{ env.VERSION_SUFFIX }}-dev
                  ${{ github.repository_owner}}/${{ matrix.binary }}:${{ env.VERSION }}-${{ env.SHORT_ARCH }}${{ env.VERSION_SUFFIX }}-modern
                  ${{ github.repository_owner}}/${{ matrix.binary }}:${{ env.VERSION }}-${{ env.SHORT_ARCH }}${{ env.VERSION_SUFFIX }}-modern-dev

            - name: Build and push (lcli)
              if: startsWith(matrix.binary, 'lcli')
              uses: docker/build-push-action@v5
              with:
                file: ./lcli/Dockerfile.cross
                context: .
                platforms: linux/${{ env.SHORT_ARCH }}
                push: true

                tags: |
                  ${{ github.repository_owner}}/${{ matrix.binary }}:${{ env.VERSION }}-${{ env.SHORT_ARCH }}${{ env.VERSION_SUFFIX }}


    build-docker-multiarch:
        name: build-docker-${{ matrix.binary }}-multiarch
        runs-on: ubuntu-22.04
        strategy:
            matrix:
                binary: [lighthouse,
                         lcli]
        needs: [build-docker-single-arch, extract-version]
        env:
            VERSION: ${{ needs.extract-version.outputs.VERSION }}
            VERSION_SUFFIX: ${{ needs.extract-version.outputs.VERSION_SUFFIX }}
        steps:
            - name: Set up Docker Buildx
              uses: docker/setup-buildx-action@v3

            - name: Dockerhub login
              run: |
                  echo "${DOCKER_PASSWORD}" | docker login --username ${DOCKER_USERNAME} --password-stdin

            - name: Create and push multiarch manifests
              run: |
                  docker buildx imagetools create -t ${{ github.repository_owner}}/${{ matrix.binary }}:${VERSION}${VERSION_SUFFIX} \
                      ${{ github.repository_owner}}/${{ matrix.binary }}:${VERSION}-arm64${VERSION_SUFFIX} \
                      ${{ github.repository_owner}}/${{ matrix.binary }}:${VERSION}-amd64${VERSION_SUFFIX};

