name: Build/publish release

on: [push, pull_request]

jobs:
  publish:
    name: Binary ${{ matrix.target }} (on ${{ matrix.os }})
    runs-on: ${{ matrix.os }}
    outputs:
      version: ${{ steps.extract_version.outputs.version }}
    strategy:
      matrix:
        include:
          - os: ubuntu-latest
            target: x86_64-unknown-linux-musl
            cross: true
            compress: true
            cargo_flags: ""
          - os: ubuntu-latest
            target: x86_64-unknown-linux-gnu
            cross: true
            compress: true
            cargo_flags: ""
          - os: ubuntu-latest
            target: aarch64-unknown-linux-musl
            cross: true
            compress: true
            cargo_flags: ""
          - os: ubuntu-latest
            target: aarch64-unknown-linux-gnu
            cross: true
            compress: true
            cargo_flags: ""
          - os: ubuntu-latest
            target: armv7-unknown-linux-musleabihf
            cross: true
            compress: true
            cargo_flags: ""
          - os: ubuntu-latest
            target: armv7-unknown-linux-gnueabihf
            cross: true
            compress: true
            cargo_flags: ""
          - os: ubuntu-latest
            target: arm-unknown-linux-musleabihf
            cross: true
            compress: true
            cargo_flags: ""
          - os: ubuntu-latest
            target: mips-unknown-linux-musl
            cross: true
            compress: false
            cargo_flags: "--no-default-features"
          - os: ubuntu-latest
            target: mipsel-unknown-linux-musl
            cross: true
            compress: true
            cargo_flags: "--no-default-features"
          - os: ubuntu-latest
            target: mips64-unknown-linux-gnuabi64
            cross: true
            compress: false
            cargo_flags: "--no-default-features"
          - os: ubuntu-latest
            target: mips64el-unknown-linux-gnuabi64
            cross: true
            compress: false
            cargo_flags: "--no-default-features"
          - os: ubuntu-latest
            target: riscv64gc-unknown-linux-gnu
            cross: true
            compress: false
            cargo_flags: "--no-default-features"
          - os: windows-latest
            target: x86_64-pc-windows-msvc
            cross: false
            compress: true
            cargo_flags: ""
          - os: macos-latest
            target: x86_64-apple-darwin
            cross: false
            compress: true
            cargo_flags: ""
          - os: ubuntu-latest
            target: x86_64-unknown-freebsd
            cross: true
            compress: false
            cargo_flags: ""

    steps:
      - name: Checkout code
        uses: actions/checkout@v2

      - name: Setup Rust toolchain
        uses: actions-rs/toolchain@v1
        with:
          toolchain: stable
          target: ${{ matrix.target }}
          override: true

      - run: sudo apt install musl-tools
        if: startsWith(matrix.os, 'ubuntu')

      - name: cargo build
        uses: actions-rs/cargo@v1
        with:
          command: build
          args: --release --locked --target=${{ matrix.target }} ${{ matrix.cargo_flags }}
          use-cross: ${{ matrix.cross }}

      - name: Set exe extension for Windows
        run: echo "EXE=.exe" >> $env:GITHUB_ENV
        if: startsWith(matrix.os, 'windows')

      - name: Compress binaries
        uses: svenstaro/upx-action@v2
        with:
          file: target/${{ matrix.target }}/release/miniserve${{ env.EXE }}
          args: --best --lzma
          strip: false  # We're stripping already in Cargo.toml
        if: ${{ matrix.compress }}

      - name: Upload artifact
        uses: actions/upload-artifact@v3
        with:
          name: ${{ matrix.target }}
          path: target/${{ matrix.target }}/release/miniserve${{ env.EXE }}

      - name: Get version from tag
        id: extract_version
        run: |
          echo ::set-output name=version::${GITHUB_REF_NAME#v}
        shell: bash

      - name: Install CHANGELOG parser
        uses: taiki-e/install-action@parse-changelog

      - name: Get CHANGELOG entry
        run: parse-changelog CHANGELOG.md ${{ steps.extract_version.outputs.version }} | tee changelog_entry
        if: startsWith(github.ref_name, 'v') && github.ref_type == 'tag'
        shell: bash

      - name: Read changelog entry from file
        id: changelog_entry
        uses: juliangruber/read-file-action@v1
        with:
          path: ./changelog_entry
        if: startsWith(github.ref_name, 'v') && github.ref_type == 'tag'

      - name: Release
        uses: svenstaro/upload-release-action@v2
        with:
          repo_token: ${{ secrets.GITHUB_TOKEN }}
          file: target/${{ matrix.target }}/release/miniserve${{ env.EXE }}
          tag: ${{ github.ref_name }}
          asset_name: miniserve-${{ steps.extract_version.outputs.version }}-${{ matrix.target }}${{ env.EXE }}
          body: ${{ steps.changelog_entry.outputs.content }}
        if: startsWith(github.ref_name, 'v') && github.ref_type == 'tag'

  container-images:
    name: Publish images
    runs-on: ubuntu-latest
    needs: publish
    # Run for tags and pushes to the default branch
    if: (startsWith(github.ref_name, 'v') && github.ref_type == 'tag') || github.event.repository.default_branch == github.ref_name

    steps:
      - name: Checkout code
        uses: actions/checkout@v2

      - name: Download artifact aarch64-unknown-linux-gnu
        uses: actions/download-artifact@v3
        with:
          name: aarch64-unknown-linux-gnu
          path: target/aarch64-unknown-linux-gnu/release

      - name: Download artifact x86_64-unknown-linux-gnu
        uses: actions/download-artifact@v3
        with:
          name: x86_64-unknown-linux-gnu
          path: target/x86_64-unknown-linux-gnu/release

      - name: Download artifact armv7-unknown-linux-gnueabihf
        uses: actions/download-artifact@v3
        with:
          name: armv7-unknown-linux-gnueabihf
          path: target/armv7-unknown-linux-gnueabihf/release

      - name: Download artifact aarch64-unknown-linux-musl
        uses: actions/download-artifact@v3
        with:
          name: aarch64-unknown-linux-musl
          path: target/aarch64-unknown-linux-musl/release

      - name: Download artifact x86_64-unknown-linux-musl
        uses: actions/download-artifact@v3
        with:
          name: x86_64-unknown-linux-musl
          path: target/x86_64-unknown-linux-musl/release

      - name: Download artifact armv7-unknown-linux-musleabihf
        uses: actions/download-artifact@v3
        with:
          name: armv7-unknown-linux-musleabihf
          path: target/armv7-unknown-linux-musleabihf/release

      - name: podman login
        run: podman login --username ${{ secrets.DOCKERHUB_USERNAME }} --password ${{ secrets.DOCKERHUB_TOKEN }} docker.io

      - name: podman build linux/arm64
        run: podman build --format docker --platform linux/arm64/v8 --manifest miniserve -f Containerfile target/aarch64-unknown-linux-gnu/release

      - name: podman build linux/amd64
        run: podman build --format docker --platform linux/amd64 --manifest miniserve -f Containerfile target/x86_64-unknown-linux-gnu/release

      - name: podman build linux/arm
        run: podman build --format docker --platform linux/arm/v7 --manifest miniserve -f Containerfile target/armv7-unknown-linux-gnueabihf/release

      - name: podman manifest push latest
        run: podman manifest push miniserve docker.io/svenstaro/miniserve:latest

      - name: podman manifest push tag version
        run: podman manifest push miniserve docker.io/svenstaro/miniserve:${{ needs.publish.outputs.version }}
        if: startsWith(github.ref_name, 'v')

      - name: podman build linux/arm64 (alpine edition)
        run: podman build --format docker --platform linux/arm64/v8 --manifest miniserve-alpine -f Containerfile.alpine target/aarch64-unknown-linux-musl/release

      - name: podman build linux/amd64 (alpine edition)
        run: podman build --format docker --platform linux/amd64 --manifest miniserve-alpine -f Containerfile.alpine target/x86_64-unknown-linux-musl/release

      - name: podman build linux/arm (alpine edition)
        run: podman build --format docker --platform linux/arm/v7 --manifest miniserve-alpine -f Containerfile.alpine target/armv7-unknown-linux-musleabihf/release

      - name: podman manifest push latest (alpine edition)
        run: podman manifest push miniserve-alpine docker.io/svenstaro/miniserve:alpine

      - name: podman manifest push tag version (alpine edition)
        run: podman manifest push miniserve-alpine docker.io/svenstaro/miniserve:${{ needs.publish.outputs.version }}-alpine
        if: startsWith(github.ref_name, 'v')
