# Credits: https://github.com/33KK 

name: Build

on:
  workflow_dispatch:
  pull_request:
  push:
    tags: ["v*.*.*"]

jobs:
  build:
    name: Build / ${{matrix.target}}

    runs-on: ${{matrix.host_os}}

    strategy:
      fail-fast: false
      matrix:
        include:
          - target: aarch64-unknown-linux-gnu
            host_os: ubuntu-20.04
            env: "JEMALLOC_SYS_WITH_LG_PAGE=16"
            use_cross: true
          - target: armv7-unknown-linux-gnueabihf
            host_os: ubuntu-20.04
            env: "JEMALLOC_SYS_WITH_LG_PAGE=16"
            use_cross: true
          #- target: arm-unknown-linux-gnueabihf
          #  host_os: ubuntu-20.04
          #  use_cross: true
          - target: x86_64-unknown-linux-gnu
            host_os: ubuntu-20.04
            use_cross: false

          - target: aarch64-unknown-linux-musl
            host_os: ubuntu-20.04
            env: "JEMALLOC_SYS_WITH_LG_PAGE=16"
            use_cross: true
          #- target: armv7-unknown-linux-musleabihf
          #  host_os: ubuntu-20.04
          #  use_cross: true
          #- target: arm-unknown-linux-musleabihf
          #  host_os: ubuntu-20.04
          #  use_cross: true
          - target: x86_64-unknown-linux-musl
            host_os: ubuntu-20.04
            use_cross: true

          - target: aarch64-apple-darwin
            host_os: macos-latest
            use_cross: false
          - target: x86_64-apple-darwin
            host_os: macos-latest
            use_cross: false

          # FIXME: waiting for ldap3 and hickory-resolver bump to ring 0.17.x
          #- target: aarch64-pc-windows-msvc
          #  host_os: windows-2022
          #  use_cross: false
          - target: x86_64-pc-windows-msvc
            host_os: windows-2022
            use_cross: false

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

      - name: Install Dependencies (Linux)
        if: startsWith(matrix.host_os, 'ubuntu')
        shell: bash
        run: |
          sudo apt-get update
          sudo apt-get install -yq build-essential

      - name: Install FoundationDB (x86_64-unknown-linux-gnu)
        if: matrix.target == 'x86_64-unknown-linux-gnu'
        run: |
          curl -LO https://github.com/apple/foundationdb/releases/download/7.1.0/foundationdb-clients_7.1.0-1_amd64.deb
          sudo dpkg -i --force-architecture foundationdb-clients_7.1.0-1_amd64.deb
          echo "USE_FOUNDATIONDB=1" >> "$GITHUB_ENV"

      - name: Install FoundationDB (x86_64-apple-darwin)
        if: matrix.target == 'x86_64-apple-darwin'
        run: |
          curl -LO https://github.com/apple/foundationdb/releases/download/7.1.34/FoundationDB-7.1.34_x86_64.pkg
          sudo installer -allowUntrusted -dumplog -pkg FoundationDB-7.1.34_x86_64.pkg -target /
          echo "USE_FOUNDATIONDB=1" >> "$GITHUB_ENV"

      - name: Rust Cache
        uses: Swatinem/rust-cache@v2
        with:
          key: ${{matrix.host_os}}-${{matrix.target}}-mail

      - name: Install Cross
        if: matrix.use_cross == true
        uses: baptiste0928/cargo-install@v2
        with:
          crate: cross
          git: https://github.com/cross-rs/cross

      - name: Build
        shell: bash
        run: |
          set -eux

          target="${{matrix.target}}"
          rustup target add "${target}"

          root="${PWD}"
          mkdir artifacts archives
          ext="${{startsWith(matrix.host_os, 'windows') == true && '.exe' || ''}}"

          # Workaround a Windows moment
          export PATH="/c/Strawberry/c/bin:/c/Strawberry/perl/site/bin:/c/Strawberry/perl/bin:$PATH"

          build() {
            ${{matrix.env}} ${{matrix.use_cross == true && 'cross' || 'cargo'}} build --release --target "${target}" "$@"
          }

          artifact() {
            local file="${1}${ext}"
            local name="${root}/archives/${2:-$1}-${target}"
            if [ "${ext}" = ".exe" ]; then
              7z a "${name}.zip" "${file}"
            else
              tar czvf "${name}.tar.gz" "${file}"
            fi
            mv "${file}" "${root}/artifacts/${2:-$1}"
          }

          mkdir -p "${root}/target/${target}/release" && cd "$_"

          if [ "${USE_FOUNDATIONDB:-0}" = 1 ]; then
            build -p mail-server --no-default-features --features "foundationdb elastic s3 redis enterprise"
            artifact stalwart-mail stalwart-mail-foundationdb
          fi

          build -p mail-server -p stalwart-cli

          artifact stalwart-mail
          artifact stalwart-cli

      - name: Upload Archives
        uses: actions/upload-artifact@v3
        with:
          name: archives
          path: ./archives

      - name: Upload Artifacts
        uses: actions/upload-artifact@v3
        with:
          name: ${{matrix.target}}
          path: ./artifacts

  release:
    name: Release

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

    permissions:
      contents: write

    steps:
      - name: Download Artifacts
        uses: actions/download-artifact@v3
        with:
          name: archives
          path: ./archives

      - name: Release
        uses: softprops/action-gh-release@v1
        with:
          files: ./archives/*
          prerelease: ${{!startsWith(github.ref, 'refs/tags/') == true && true || null}}
          tag_name: ${{!startsWith(github.ref, 'refs/tags/') == true && 'nightly' || null}}


  docker_build:
    name: Docker Build

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

    permissions:
      packages: write

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

      - name: Set Up Docker Buildx
        uses: docker/setup-buildx-action@v2

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

      - name: Log In to GitHub Container Registry
        uses: docker/login-action@v2
        with:
          registry: ghcr.io
          username: ${{github.repository_owner}}
          password: ${{github.token}}

      - name: Log In to DockerHub
        uses: docker/login-action@v2
        with:
          username: ${{secrets.DOCKERHUB_USERNAME}}
          password: ${{secrets.DOCKERHUB_TOKEN}}

      - name: Extract Metadata for Docker
        id: meta
        uses: docker/metadata-action@v4
        with:
          images: |
            ${{github.repository}}
            ghcr.io/${{github.repository}}
          tags: |
            type=ref,event=tag
            type=edge,branch=main

      - name: Build and Push Docker Images
        id: build
        uses: docker/build-push-action@v4
        with:
          context: .
          push: true
          platforms: linux/amd64,linux/arm64
          tags: ${{steps.meta.outputs.tags}}
          labels: ${{steps.meta.outputs.labels}}
