# Workflow that builds Quassel on various Linux distros, and creates packages for both Windows and macOS.
# For tagged pushes, a draft release is automatically created, using the tag message as release description
# and attaching Windows and macOS builds, as well as the source archive.
name: Quassel CI

on:
  push:
  pull_request:
  schedule:
    # * is a special character in YAML so you have to quote this string
    # Run at 13:37 on the 14th of every month (odd time to reduce load)
    - cron: '37 13 14 * *'

# Can't use simpler definition of [ push, pull_request, schedule ]
# See https://www.jeffgeerling.com/blog/2020/running-github-actions-workflow-on-schedule-and-other-events

defaults:
  run:
    shell: bash

jobs:

# ------------------------------------------------------------------------------------------------------------------------------------------
  build-linux:
    name: Linux
    runs-on: ubuntu-latest
    container: quassel/quassel-build-env:${{ matrix.dist }}
    strategy:
      fail-fast: false
      matrix:
        dist: [ debian-stable, debian-testing, ubuntu-xenial, ubuntu-bionic, ubuntu-focal, ubuntu-groovy ]
        cxx: [ 'g++', 'clang++' ]
        with-kde: [ -DWITH_KDE=ON ]
        extra-options: [ -DWITH_WEBENGINE=ON ]
        include:
          # Baseline, test more combinations
          - dist: ubuntu-xenial
            with-kde: -DWITH_KDE=OFF
            extra-options: -DWITH_WEBKIT=ON
          - dist: ubuntu-xenial
            with-kde: -DWITH_KDE=ON
            extra-options: -DWITH_WEBKIT=ON
        exclude:
          # QtWebEngine is not available on Xenial
          - dist: ubuntu-xenial
            extra-options: -DWITH_WEBENGINE=ON
    env:
        CCACHE_BASEDIR: ${{ github.workspace }}
        CCACHE_DIR: ${{ github.workspace }}/ccache
        CCACHE_MAXSIZE: 100M
        CXX: ${{ matrix.cxx }}

    steps:
    - name: Check out source code
      uses: actions/checkout@v2

    - name: Get timestamp
      id: get-timestamp
      run: echo "::set-output name=timestamp::$(date -u "+%F-%R")"

    - name: Setup ccache
      uses: actions/cache@v2
      with:
        path: ${{ github.workspace }}/ccache
        key: ${{ matrix.dist }}-ccache-${{ steps.get-timestamp.outputs.timestamp }}
        restore-keys: |
             ${{ matrix.dist }}-ccache-

    - name: Zero ccache stats
      run: ccache -z

    - name: Configure
      run: |
        mkdir build
        cd build && cmake $GITHUB_WORKSPACE \
                          -GNinja \
                          -DCMAKE_BUILD_TYPE=Release \
                          -DBUILD_TESTING=ON \
                          -DFATAL_WARNINGS=ON \
                          ${{ matrix.with-kde }} \
                          ${{ matrix.extra-options }}

    - name: Build
      run: cd build && ninja

    - name: Run tests
      run: cd build && ctest

    - name: Install
      run: cd build && DESTDIR=$GITHUB_WORKSPACE/image ninja install

    - name: Print ccache stats
      run: ccache -s

# ------------------------------------------------------------------------------------------------------------------------------------------
  build-macos:
    name: macOS
    runs-on: macos-latest
    env:
      CCACHE_BASEDIR: ${{ github.workspace }}
      CCACHE_DIR: ${{ github.workspace }}/ccache
      CCACHE_MAXSIZE: 100M

    steps:
    - name: Select Xcode version
      uses: maxim-lobanov/setup-xcode@v1
      with:
        # Newer Xcode versions may not officially be supported by Qt
        # Check https://doc.qt.io/qt-5/macos.html
        xcode-version: '12.4.0'

    - name: Check out source code
      uses: actions/checkout@v2
      with:
        fetch-depth: 0  # so git-describe works

    - name: Fetch tag information
      if: startsWith(github.ref, 'refs/tags/')
      run: git fetch -f origin $GITHUB_REF:$GITHUB_REF

    - name: Install dependencies
      # Skip "brew update" as it can trigger 50+ minutes of updating.
      # GitHub Actions intentionally disables the default auto-update on their
      # macOS CI images (and macOS CI images usually update once a week).
      #
      # See https://github.com/actions/virtual-environments/issues/2173
      # > We've set no auto-update intentionally here [...]
      # And https://github.com/microsoft/appcenter/issues/293
      #
      # If Homebrew begins failing in the future due to out-of-date versions,
      # it can be re-enabled here as follows...
      # run: brew update && [below command]
      run: brew install boost ccache ninja qca qt@5

    - name: Get timestamp
      id: get-timestamp
      run: echo "::set-output name=timestamp::$(date -u "+%F-%R")"

    - name: Setup ccache
      uses: actions/cache@v2
      with:
        path: ${{ github.workspace }}/ccache
        key: macos-ccache-${{ steps.get-timestamp.outputs.timestamp }}
        restore-keys: |
             macos-ccache-

    - name: Zero ccache stats
      run: ccache -z

    - name: Configure
      run: |
        mkdir build
        cd build && cmake $GITHUB_WORKSPACE \
                          -GNinja \
                          -DWANT_CORE=ON \
                          -DWANT_QTCLIENT=ON \
                          -DWANT_MONO=ON \
                          -DCMAKE_PREFIX_PATH=$(brew --prefix)/opt/qt@5 \
                          -DCMAKE_INSTALL_PREFIX=$GITHUB_WORKSPACE/bundles \
                          -DCMAKE_BUILD_TYPE=Release \
                          -DBUILD_TESTING=ON \
                          -DFATAL_WARNINGS=OFF \
                          -DENABLE_SHARED=OFF \
                          -DBUNDLE=ON \

    - name: Build
      run: cd build && ninja

    - name: Run tests
      run: cd build && ctest

    - name: Install
      run: cd build && ninja install

    - name: Print ccache stats
      run: ccache -s

    - name: Upload artifacts
      uses: actions/upload-artifact@v2
      with:
        name: macOS
        path: ${{ github.workspace }}/bundles/*.dmg

# ------------------------------------------------------------------------------------------------------------------------------------------
  build-windows:
    name: Windows
    runs-on: windows-latest
    env:
      WORKSPACE: ${{ github.workspace }}
      CRAFT: /C/CraftMaster/windows-msvc2019_64-cl/craft/bin/craft.py

    steps:
    - name: Check out source code
      uses: actions/checkout@v2
      with:
        fetch-depth: 0  # so git-describe works

    - name: Fetch tag information
      if: startsWith(github.ref, 'refs/tags/')
      run: git fetch -f origin $GITHUB_REF:$GITHUB_REF

    - name: Clone CraftMaster
      run: git clone --depth=1 https://invent.kde.org/kde/craftmaster.git /C/CraftMaster/CraftMaster

    - name: Configure CraftMaster
      run: python /C/CraftMaster/CraftMaster/CraftMaster.py --config $WORKSPACE/.craftsettings.ini --variables "WORKSPACE=$WORKSPACE"

    - name: Add Quassel blueprint
      run: python $CRAFT --add-blueprint-repository https://github.com/quassel/craft-blueprints-quassel.git

    - name: Install NSIS
      run: python $CRAFT dev-utils/nsis

    - name: Install dependencies
      run: python $CRAFT --install-deps quassel/quassel

    - name: Build
      run: python $CRAFT --no-cache --src-dir $WORKSPACE quassel/quassel

    - name: Run tests
      run: python $CRAFT --no-cache --src-dir $WORKSPACE --test quassel/quassel

    - name: Package
      run: python $CRAFT --no-cache --src-dir $WORKSPACE --package quassel/quassel

    - name: Upload artifacts
      uses: actions/upload-artifact@v2
      with:
        name: Windows
        path: ${{ github.workspace }}/packages/*

# ------------------------------------------------------------------------------------------------------------------------------------------
  post-build:
    name: Post-Build
    runs-on: ubuntu-latest
    needs: [ build-linux, build-macos, build-windows ]
    env:
      GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

    steps:
    - name: Check out source code
      uses: actions/checkout@v2

    - name: Fetch tag information
      if: startsWith(github.ref, 'refs/tags/')
      run: git fetch -f origin $GITHUB_REF:$GITHUB_REF

    - name: Download artifacts
      uses: actions/download-artifact@v2
      with:
        path: artifacts

    - name: List artifacts
      run: ls -lhR artifacts

    - name: Check artifacts
      run: |
        # Sanity check: We should have exactly 5 files matching the given patterns
        [[ 5 -eq $(find artifacts/ \( -type f -name 'Quassel*.dmg' -o -name 'quassel*.exe' -o -name 'quassel*.7z' \) -printf '.' | wc -c) ]]

    - name: Create release notes
      if: startsWith(github.ref, 'refs/tags/')
      run: |
        # Use the tag's annotation as release notes
        TAGNAME=$(git rev-parse --abbrev-ref $GITHUB_REF)
        MESSAGE=$(git tag -l --format='%(contents)' $TAGNAME | perl -ne 'print if not /-----BEGIN PGP SIGNATURE-----/../-----END PGP SIGNATURE-----/')
        echo -e "Quassel $TAGNAME\n\n$MESSAGE" > release_notes.txt

    - name: Prepare source archive
      if: startsWith(github.ref, 'refs/tags/')
      run: |
        mkdir assets
        TAGNAME=$(git rev-parse --abbrev-ref $GITHUB_REF)
        git archive --format=tar --prefix=quassel-$TAGNAME/ $TAGNAME | xz > assets/quassel-$TAGNAME.tar.xz

    - name: Prepare packages for release
      if: startsWith(github.ref, 'refs/tags/')
      run: |
        TAGNAME=$(git rev-parse --abbrev-ref $GITHUB_REF)
        for type in Client Core Mono; do
          mv artifacts/macOS/Quassel$type*.dmg assets/Quassel$type-macOS-$TAGNAME.dmg
        done
        mv artifacts/Windows/quassel-*.exe assets/quassel-windows-setup-$TAGNAME.exe
        mv artifacts/Windows/quassel-*.7z assets/quassel-windows-$TAGNAME.7z

    - name: Create checksums for release assets
      if: startsWith(github.ref, 'refs/tags/')
      run: find assets/ -type f -execdir sh -c 'sha256sum "$1" > "$1.sha256sum"' _ {} \;

    - name: Create draft release
      if: startsWith(github.ref, 'refs/tags/')
      run: |
        # The stock upload-release-asset action can only handle single files
        # Instead, use the hub utility so we can upload all assets at once
        assets=()
        for asset in assets/*; do assets+=("-a" "$asset"); done
        hub release create -d "${assets[@]}" -F release_notes.txt `git rev-parse --abbrev-ref $GITHUB_REF`
