---
name: CI

on:
  pull_request:
    branches: [master, nightly]
    types: [opened, synchronize, reopened]
  push:
    branches: [master, nightly]
  workflow_dispatch:

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

jobs:
  github_env:
    name: GitHub Env Debug
    runs-on: ubuntu-latest

    steps:
      - name: Dump github context
        run: echo "$GITHUB_CONTEXT"
        shell: bash
        env:
          GITHUB_CONTEXT: ${{ toJson(github) }}

  check_changelog:
    name: Check Changelog
    runs-on: ubuntu-latest
    steps:
      - name: Checkout
        if: ${{ github.ref == 'refs/heads/master' || github.base_ref == 'master' }}
        uses: actions/checkout@v3

      - name: Verify Changelog
        id: verify_changelog
        if: ${{ github.ref == 'refs/heads/master' || github.base_ref == 'master' }}
        # base_ref for pull request check, ref for push
        uses: LizardByte/.github/actions/verify_changelog@master
        with:
          token: ${{ secrets.GITHUB_TOKEN }}
    outputs:
      next_version: ${{ steps.verify_changelog.outputs.changelog_parser_version }}
      next_version_bare: ${{ steps.verify_changelog.outputs.changelog_parser_version_bare }}
      last_version: ${{ steps.verify_changelog.outputs.latest_release_tag_name }}
      release_body: ${{ steps.verify_changelog.outputs.changelog_parser_description }}

  # todo - remove this job once versioning is fully automated by cmake
  check_versions:
    name: Check Versions
    runs-on: ubuntu-latest
    needs: check_changelog
    if: ${{ github.ref == 'refs/heads/master' || github.base_ref == 'master' }}
    # base_ref for pull request check, ref for push
    steps:
      - name: Checkout
        uses: actions/checkout@v3

      - name: Check CMakeLists.txt Version
        run: |
          version=$(grep -o -E '^project\(Sunshine VERSION [0-9]+\.[0-9]+\.[0-9]+' CMakeLists.txt | \
            grep -o -E '[0-9]+\.[0-9]+\.[0-9]+')
          echo "cmakelists_version=${version}" >> $GITHUB_ENV

      - name: Compare CMakeList.txt Version
        if: ${{ env.cmakelists_version != needs.check_changelog.outputs.next_version_bare }}
        run: |
          echo CMakeLists version: "$cmakelists_version"
          echo Changelog version: "${{ needs.check_changelog.outputs.next_version_bare }}"
          echo Within 'CMakeLists.txt' change "project(Sunshine [VERSION $cmakelists_version]" to \
            "project(Sunshine [VERSION ${{ needs.check_changelog.outputs.next_version_bare }}]"
          exit 1

  setup_release:
    name: Setup Release
    needs: check_changelog
    runs-on: ubuntu-latest
    steps:
      - name: Set release details
        id: release_details
        env:
          RELEASE_BODY: ${{ needs.check_changelog.outputs.release_body }}
        run: |
          # determine to create a release or not
          if [[ $GITHUB_EVENT_NAME == "push" ]]; then
            RELEASE=true
          else
            RELEASE=false
          fi

          # set the release tag
          COMMIT=${{ github.sha }}
          if [[ $GITHUB_REF == refs/heads/master ]]; then
            TAG="${{ needs.check_changelog.outputs.next_version }}"
            RELEASE_NAME="${{ needs.check_changelog.outputs.next_version }}"
            RELEASE_BODY="$RELEASE_BODY"
            PRE_RELEASE="false"
          elif [[ $GITHUB_REF == refs/heads/nightly ]]; then
            TAG="nightly-dev"
            RELEASE_NAME="nightly"
            RELEASE_BODY="automated nightly release - $(date -u +'%Y-%m-%dT%H:%M:%SZ') - ${COMMIT}"
            PRE_RELEASE="true"
          fi

          echo "create_release=${RELEASE}" >> $GITHUB_OUTPUT
          echo "release_tag=${TAG}" >> $GITHUB_OUTPUT
          echo "release_commit=${COMMIT}" >> $GITHUB_OUTPUT
          echo "release_name=${RELEASE_NAME}" >> $GITHUB_OUTPUT
          echo "pre_release=${PRE_RELEASE}" >> $GITHUB_OUTPUT

          # this is stupid but works for multiline strings
          echo "RELEASE_BODY<<EOF" >> $GITHUB_ENV
          echo "$RELEASE_BODY" >> $GITHUB_ENV
          echo "EOF" >> $GITHUB_ENV

    outputs:
      create_release: ${{ steps.release_details.outputs.create_release }}
      release_tag: ${{ steps.release_details.outputs.release_tag }}
      release_commit: ${{ steps.release_details.outputs.release_commit }}
      release_name: ${{ steps.release_details.outputs.release_name }}
      release_body: ${{ env.RELEASE_BODY }}
      pre_release: ${{ steps.release_details.outputs.pre_release }}

  setup_flatpak_matrix:
    name: Setup Flatpak Matrix
    runs-on: ubuntu-latest
    steps:
      - name: Set release details
        id: flatpak_matrix
        # https://www.cynkra.com/blog/2020-12-23-dynamic-gha
        run: |
          # determine which architectures to build
          if [[ $GITHUB_EVENT_NAME == "push" ]]; then
            matrix=$((
              echo '{ "arch" : ["x86_64", "aarch64"] }'
            ) | jq -c .)
          else
            matrix=$((
              echo '{ "arch" : ["x86_64"] }'
            ) | jq -c .)
          fi

          echo $matrix
          echo $matrix | jq .
          echo "matrix=$matrix" >> $GITHUB_OUTPUT

    outputs:
      matrix: ${{ steps.flatpak_matrix.outputs.matrix }}

  build_linux_flatpak:
    name: Linux Flatpak
    runs-on: ubuntu-22.04
    needs: [setup_release, setup_flatpak_matrix]
    strategy:
      fail-fast: false  # false to test all, true to fail entire job if any fail
      matrix: ${{fromJson(needs.setup_flatpak_matrix.outputs.matrix)}}

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

      - name: Setup Dependencies Linux Flatpak
        run: |
          PLATFORM_VERSION=22.08

          sudo apt-get update -y
          sudo apt-get install -y \
            cmake \
            flatpak \
            qemu-user-static
          sudo su $(whoami) -c "flatpak --user remote-add --if-not-exists flathub \
            https://flathub.org/repo/flathub.flatpakrepo"
          sudo su $(whoami) -c "flatpak --user install -y flathub \
            org.flatpak.Builder \
            org.freedesktop.Platform/${{ matrix.arch }}/${PLATFORM_VERSION} \
            org.freedesktop.Sdk/${{ matrix.arch }}/${PLATFORM_VERSION} \
            org.freedesktop.Sdk.Extension.node18/${{ matrix.arch }}/${PLATFORM_VERSION} \
            "

      - name: Cache Flatpak build
        uses: actions/cache@v3
        with:
          path: ./build/.flatpak-builder
          key: flatpak-${{ matrix.arch }}-${{ github.sha }}
          restore-keys: |
            flatpak-${{ matrix.arch }}-

      - name: Configure Flatpak Manifest
        run: |
          # variables for manifest
          branch=${GITHUB_HEAD_REF}

          # check the branch variable
          if [ -z "$branch" ]
          then
            echo "This is a PUSH event"
            branch=${{ github.ref_name }}
            commit=${{ github.sha }}
            clone_url=${{ github.event.repository.clone_url }}
          else
            echo "This is a PR event"
            commit=${{ github.event.pull_request.head.sha }}
            clone_url=${{ github.event.pull_request.head.repo.clone_url }}
          fi
          echo "Branch: ${branch}"
          echo "Commit: ${commit}"
          echo "Clone URL: ${clone_url}"

          mkdir -p build
          mkdir -p artifacts

          cd build
          cmake -DGITHUB_CLONE_URL=${clone_url} \
            -DGITHUB_BRANCH=${branch} \
            -DGITHUB_COMMIT=${commit} \
            -DSUNSHINE_CONFIGURE_FLATPAK_MAN=ON \
            -DSUNSHINE_CONFIGURE_ONLY=ON \
            ..

      - name: Build Linux Flatpak
        working-directory: build
        run: |
          sudo su $(whoami) -c 'flatpak run org.flatpak.Builder --arch=${{ matrix.arch }} --repo=repo --force-clean \
            --stop-at=cuda build-sunshine dev.lizardbyte.sunshine.yml'
          cp -r .flatpak-builder copy-of-flatpak-builder
          sudo su $(whoami) -c 'flatpak run org.flatpak.Builder --arch=${{ matrix.arch }} --repo=repo --force-clean \
            build-sunshine dev.lizardbyte.sunshine.yml'
          rm -rf .flatpak-builder
          mv copy-of-flatpak-builder .flatpak-builder
          sudo su $(whoami) -c 'flatpak build-bundle --arch=${{ matrix.arch }} ./repo \
            ../artifacts/sunshine_${{ matrix.arch }}.flatpak dev.lizardbyte.sunshine'
          sudo su $(whoami) -c 'flatpak build-bundle --runtime --arch=${{ matrix.arch }} ./repo \
            ../artifacts/sunshine_debug_${{ matrix.arch }}.flatpak dev.lizardbyte.sunshine.Debug'

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

      - name: Create/Update GitHub Release
        if: ${{ needs.setup_release.outputs.create_release == 'true' }}
        uses: ncipollo/release-action@v1
        with:
          name: ${{ needs.setup_release.outputs.release_name }}
          tag: ${{ needs.setup_release.outputs.release_tag }}
          commit: ${{ needs.setup_release.outputs.release_commit }}
          artifacts: "*artifacts/*"
          token: ${{ secrets.GH_BOT_TOKEN }}
          allowUpdates: true
          body: ${{ needs.setup_release.outputs.release_body }}
          discussionCategory: announcements
          prerelease: ${{ needs.setup_release.outputs.pre_release }}

  build_linux:
    name: Linux
    runs-on: ubuntu-${{ matrix.dist }}
    needs: [check_changelog, setup_release]
    strategy:
      fail-fast: false  # false to test all, true to fail entire job if any fail
      matrix:
        include:  # package these differently
          - type: appimage
            EXTRA_ARGS: '-DSUNSHINE_CONFIGURE_APPIMAGE=ON'
            dist: 20.04

    steps:
      - name: Checkout
        uses: actions/checkout@v3
        with:
          submodules: recursive

      - name: Setup Dependencies Linux
        run: |
          sudo add-apt-repository ppa:ubuntu-toolchain-r/test -y

          if [[ ${{ matrix.dist }} == "18.04" ]]; then
            # Ubuntu 18.04 packages
            sudo add-apt-repository ppa:savoury1/boost-defaults-1.71 -y

            sudo apt-get update -y
            sudo apt-get install -y \
              libboost-filesystem1.71-dev \
              libboost-locale1.71-dev \
              libboost-log1.71-dev \
              libboost-regex1.71-dev \
              libboost-thread1.71-dev \
              libboost-program-options1.71-dev

            # Install cmake
            wget https://cmake.org/files/v3.22/cmake-3.22.2-linux-x86_64.sh
            chmod +x cmake-3.22.2-linux-x86_64.sh
            mkdir /opt/cmake
            ./cmake-3.22.2-linux-x86_64.sh --prefix=/opt/cmake --skip-license
            ln --force --symbolic /opt/cmake/bin/cmake /usr/local/bin/cmake
            cmake --version

            # install newer tar from focal... appimagelint fails on 18.04 without this
            echo "original tar version"
            tar --version
            wget -O tar.deb http://security.ubuntu.com/ubuntu/pool/main/t/tar/tar_1.30+dfsg-7ubuntu0.20.04.2_amd64.deb
            sudo apt-get -y install -f ./tar.deb
            echo "new tar version"
            tar --version
          else
            # Ubuntu 20.04+ packages
            sudo apt-get update -y
            sudo apt-get install -y \
              cmake \
              libboost-filesystem-dev \
              libboost-locale-dev \
              libboost-log-dev \
              libboost-thread-dev \
              libboost-program-options-dev
          fi

          sudo apt-get install -y \
            build-essential \
            gcc-10 \
            g++-10 \
            libappindicator3-dev \
            libavdevice-dev \
            libcap-dev \
            libcurl4-openssl-dev \
            libdrm-dev \
            libevdev-dev \
            libmfx-dev \
            libnuma-dev \
            libopus-dev \
            libpulse-dev \
            libssl-dev \
            libva-dev \
            libvdpau-dev \
            libwayland-dev \
            libx11-dev \
            libxcb-shm0-dev \
            libxcb-xfixes0-dev \
            libxcb1-dev \
            libxfixes-dev \
            libxrandr-dev \
            libxtst-dev \
            wget

          # clean apt cache
          sudo apt-get clean
          sudo rm -rf /var/lib/apt/lists/*

          # Update gcc alias
          # https://stackoverflow.com/a/70653945/11214013
          sudo update-alternatives --install \
            /usr/bin/gcc gcc /usr/bin/gcc-10 100 \
            --slave /usr/bin/g++ g++ /usr/bin/g++-10 \
            --slave /usr/bin/gcov gcov /usr/bin/gcov-10 \
            --slave /usr/bin/gcc-ar gcc-ar /usr/bin/gcc-ar-10 \
            --slave /usr/bin/gcc-ranlib gcc-ranlib /usr/bin/gcc-ranlib-10

          # Install CUDA
          sudo wget \
            https://developer.download.nvidia.com/compute/cuda/11.8.0/local_installers/cuda_11.8.0_520.61.05_linux.run \
            --progress=bar:force:noscroll -q --show-progress -O /root/cuda.run
          sudo chmod a+x /root/cuda.run
          sudo /root/cuda.run --silent --toolkit --toolkitpath=/usr --no-opengl-libs --no-man-page --no-drm
          sudo rm /root/cuda.run

      - name: Build Linux
        env:
          BRANCH: ${{ github.head_ref || github.ref_name }}
          BUILD_VERSION: ${{ needs.check_changelog.outputs.next_version_bare }}
          COMMIT: ${{ github.event.pull_request.head.sha || github.sha }}
        run: |
          mkdir -p build
          mkdir -p artifacts

          npm install

          cd build
          cmake -DCMAKE_BUILD_TYPE=Release \
            -DCMAKE_INSTALL_PREFIX=/usr \
            -DSUNSHINE_ASSETS_DIR=share/sunshine \
            -DSUNSHINE_EXECUTABLE_PATH=/usr/bin/sunshine \
            -DSUNSHINE_ENABLE_WAYLAND=ON \
            -DSUNSHINE_ENABLE_X11=ON \
            -DSUNSHINE_ENABLE_DRM=ON \
            -DSUNSHINE_ENABLE_CUDA=ON \
            ${{ matrix.EXTRA_ARGS }} \
            ..
          make -j ${nproc}

      - name: Package Linux - CPACK
        if: ${{ matrix.type == 'cpack' }}
        working-directory: build
        run: |
          cpack -G DEB
          mv ./cpack_artifacts/Sunshine.deb ../artifacts/sunshine-${{ matrix.dist }}.deb

          if [[ ${{ matrix.dist }} == "20.04" ]]; then
            cpack -G RPM
            mv ./cpack_artifacts/Sunshine.rpm ../artifacts/sunshine.rpm
          fi

      - name: Set AppImage Version
        if: ${{ matrix.type == 'appimage' && ( needs.check_changelog.outputs.next_version_bare != needs.check_changelog.outputs.last_version ) }}  # yamllint disable-line rule:line-length
        run: |
          version=${{ needs.check_changelog.outputs.next_version_bare }}
          echo "VERSION=${version}" >> $GITHUB_ENV

      - name: Package Linux - AppImage
        if: ${{ matrix.type == 'appimage' }}
        working-directory: build
        run: |
          # install sunshine to the DESTDIR
          make install DESTDIR=AppDir

          # custom AppRun file
          cp -f ../packaging/linux/AppImage/AppRun ./AppDir/
          chmod +x ./AppDir/AppRun

          # variables
          DESKTOP_FILE="${DESKTOP_FILE:-sunshine.desktop}"
          ICON_FILE="${ICON_FILE:-sunshine.png}"

          # AppImage
          # https://docs.appimage.org/packaging-guide/index.html
          wget https://github.com/linuxdeploy/linuxdeploy/releases/download/continuous/linuxdeploy-x86_64.AppImage
          chmod +x linuxdeploy-x86_64.AppImage

          ./linuxdeploy-x86_64.AppImage \
            --appdir ./AppDir \
            --executable ./sunshine \
            --icon-file "../$ICON_FILE" \
            --desktop-file "./$DESKTOP_FILE" \
            --library /usr/lib/x86_64-linux-gnu/libpango-1.0.so.0 \
            --library /usr/lib/x86_64-linux-gnu/libpangocairo-1.0.so.0 \
            --library /usr/lib/x86_64-linux-gnu/libpangoft2-1.0.so.0 \
            --output appimage

          # move
          mv Sunshine*.AppImage ../artifacts/sunshine.AppImage

          # permissions
          chmod +x ../artifacts/sunshine.AppImage

      - name: Verify AppImage
        if: ${{ matrix.type == 'appimage' }}
        run: |
          wget https://github.com/TheAssassin/appimagelint/releases/download/continuous/appimagelint-x86_64.AppImage
          chmod +x appimagelint-x86_64.AppImage

          # rm -rf ~/.cache/appimagelint/

          ./appimagelint-x86_64.AppImage ./artifacts/sunshine.AppImage

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

      - name: Create/Update GitHub Release
        if: ${{ needs.setup_release.outputs.create_release == 'true' }}
        uses: ncipollo/release-action@v1
        with:
          name: ${{ needs.setup_release.outputs.release_name }}
          tag: ${{ needs.setup_release.outputs.release_tag }}
          commit: ${{ needs.setup_release.outputs.release_commit }}
          artifacts: "*artifacts/*"
          token: ${{ secrets.GH_BOT_TOKEN }}
          allowUpdates: true
          body: ${{ needs.setup_release.outputs.release_body }}
          discussionCategory: announcements
          prerelease: ${{ needs.setup_release.outputs.pre_release }}

  build_mac:
    name: MacOS
    runs-on: macos-11
    needs: [check_changelog, setup_release]

    steps:
      - name: Checkout
        uses: actions/checkout@v3
        with:
          submodules: recursive

      - name: Setup Dependencies MacOS
        run: |
          # install dependencies using homebrew
          brew install boost cmake curl node opus pkg-config

          # fix openssl header not found
          ln -sf /usr/local/opt/openssl/include/openssl /usr/local/include/openssl

      - name: Build MacOS
        env:
          BRANCH: ${{ github.head_ref || github.ref_name }}
          BUILD_VERSION: ${{ needs.check_changelog.outputs.next_version_bare }}
          COMMIT: ${{ github.event.pull_request.head.sha || github.sha }}
        run: |
          npm install

          mkdir build
          cd build
          cmake -DCMAKE_BUILD_TYPE=Release \
            -DCMAKE_INSTALL_PREFIX=/usr \
            -DSUNSHINE_ASSETS_DIR=local/sunshine/assets \
            -DSUNSHINE_EXECUTABLE_PATH=/usr/bin/sunshine \
            ..
          make -j ${nproc}

      - name: Package MacOS
        run: |
          mkdir -p artifacts
          cd build

          # package
          cpack -G DragNDrop
          mv ./cpack_artifacts/Sunshine.dmg ../artifacts/sunshine.dmg

          # cpack -G Bundle
          # mv ./cpack_artifacts/Sunshine.dmg ../artifacts/sunshine-bundle.dmg

      - name: Upload Artifacts
        uses: actions/upload-artifact@v3
        with:
          name: sunshine-macos
          path: artifacts/

      - name: Create/Update GitHub Release
        if: ${{ needs.setup_release.outputs.create_release == 'true' }}
        uses: ncipollo/release-action@v1
        with:
          name: ${{ needs.setup_release.outputs.release_name }}
          tag: ${{ needs.setup_release.outputs.release_tag }}
          commit: ${{ needs.setup_release.outputs.release_commit }}
          artifacts: "*artifacts/*"
          token: ${{ secrets.GH_BOT_TOKEN }}
          allowUpdates: true
          body: ${{ needs.setup_release.outputs.release_body }}
          discussionCategory: announcements
          prerelease: ${{ needs.setup_release.outputs.pre_release }}

  build_mac_port:
    name: Macports
    needs: [check_changelog, setup_release]
    runs-on: macos-11

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

      - name: Checkout ports
        uses: actions/checkout@v3
        with:
          repository: macports/macports-ports
          fetch-depth: 64
          path: ports

      - name: Checkout mpbb
        uses: actions/checkout@v3
        with:
          repository: macports/mpbb
          path: mpbb

      - name: Setup Dependencies Macports
        run: |
          # install dependencies using homebrew
          brew install cmake

      - name: Configure Portfile
        run: |
          # variables for Portfile
          branch=${GITHUB_HEAD_REF}

          # check the branch variable
          if [ -z "$branch" ]
          then
            echo "This is a PUSH event"
            commit=${{ github.sha }}
            clone_url=${{ github.event.repository.clone_url }}
          else
            echo "This is a PR event"
            commit=${{ github.event.pull_request.head.sha }}
            clone_url=${{ github.event.pull_request.head.repo.clone_url }}
          fi
          echo "Commit: ${commit}"
          echo "Clone URL: ${clone_url}"

          mkdir build
          cd build
          cmake \
            -DGITHUB_COMMIT=${commit} \
            -DGITHUB_CLONE_URL=${clone_url} \
            -DSUNSHINE_CONFIGURE_PORTFILE=ON \
            -DSUNSHINE_CONFIGURE_ONLY=ON \
            ..
          cd ..

          # copy Portfile to artifacts
          mkdir -p artifacts
          cp -f ./build/Portfile ./artifacts/

          # copy Portfile to ports
          mkdir -p ./ports/multimedia/Sunshine
          cp -f ./build/Portfile ./ports/multimedia/Sunshine/Portfile

          # testing
          cat ./artifacts/Portfile

      - name: Bootstrap MacPorts
        run: |
          . ports/.github/workflows/bootstrap.sh

          # Add getopt, mpbb and the MacPorts paths to $PATH for the subsequent steps.
          echo "/opt/mports/bin" >> $GITHUB_PATH
          echo "${PWD}/mpbb" >> $GITHUB_PATH
          echo "/opt/local/bin" >> $GITHUB_PATH
          echo "/opt/local/sbin" >> $GITHUB_PATH

      - name: Determine list of subports
        id: subportlist
        run: |
          set -eu
          port=Sunshine
          subportlist=""

          echo "Listing subports for Sunshine"
          new_subports=$(mpbb \
            --work-dir /tmp/mpbb \
            list-subports \
            --archive-site= \
            --archive-site-private= \
            --include-deps=no \
            "$port" \
            | tr '\n' ' ')
          for subport in $new_subports; do
            echo "$subport"
            subportlist="$subportlist $subport"
          done
          echo "subportlist=${subportlist}" >> $GITHUB_OUTPUT

      - name: Run port lint for all subports
        env:
          subportlist: ${{ steps.subportlist.outputs.subportlist }}
        run: |
          set -eu
          fail=0
          for subport in $subportlist; do
            echo "::group::${subport}"
            path=$(port file "$subport")
            messagetype="warning"
            if ! messages=$(port -q lint "$subport" 2>&1); then
              messagetype="error"
              fail=1
            fi
            if [ -n "$messages" ]; then
              echo "$messages"
              # See https://github.com/actions/toolkit/issues/193#issuecomment-605394935
              encoded_messages="port lint ${subport}:%0A"
              encoded_messages+="$(echo "${messages}" | sed -E 's/$/%0A/g' | tr -d '\n')"
              echo "::${messagetype} file=${path#${PWD}/ports/},line=1,col=1::${encoded_messages}"
            fi
            echo "::endgroup::"
          done
          exit "$fail"

      - name: Build subports
        env:
          subportlist: ${{ steps.subportlist.outputs.subportlist }}
        run: |
          set -eu
          fail=0
          for subport in $subportlist; do
            workdir="/tmp/mpbb/$subport"
            mkdir -p "$workdir/logs"
            touch "$workdir/logs/dependencies-progress.txt"
            echo "::group::Cleaning up between ports"
            sudo mpbb --work-dir "$workdir" cleanup
            echo "::endgroup::"
            echo "::group::Installing dependencies for ${subport}"
            sudo mpbb \
              --work-dir "$workdir" \
              install-dependencies \
              "$subport" >"$workdir/logs/install-dependencies.log" 2>&1 &
            deps_pid=$!
            tail -f "$workdir/logs/dependencies-progress.txt" 2>/dev/null &
            tail_pid=$!
            set +e
            wait "$deps_pid"
            deps_exit=$?
            set -e
            kill "$tail_pid" || true
            if [ "$deps_exit" -ne 0 ]; then
              echo "::endgroup::"
              echo "::error::Failed to install dependencies for ${subport}"
              fail=1
              continue
            fi
            echo "::endgroup::"
            echo "::group::Installing ${subport}"
            set +e
            sudo mpbb \
              --work-dir "$workdir" \
              install-port \
              --source \
              "$subport"
            install_exit=$?
            set -e
            if [ "$install_exit" -ne 0 ]; then
              echo "::endgroup::"
              echo "::error::Failed to install ${subport}"
              fail=1
              continue
            fi
            echo "::endgroup::"
          done
          exit "$fail"

      - name: Upload Artifacts
        uses: actions/upload-artifact@v3
        with:
          name: sunshine-macports
          path: artifacts/

      - name: Create/Update GitHub Release
        if: ${{ needs.setup_release.outputs.create_release == 'true' }}
        uses: ncipollo/release-action@v1
        with:
          name: ${{ needs.setup_release.outputs.release_name }}
          tag: ${{ needs.setup_release.outputs.release_tag }}
          commit: ${{ needs.setup_release.outputs.release_commit }}
          artifacts: "*artifacts/*"
          token: ${{ secrets.GH_BOT_TOKEN }}
          allowUpdates: true
          body: ${{ needs.setup_release.outputs.release_body }}
          discussionCategory: announcements
          prerelease: ${{ needs.setup_release.outputs.pre_release }}

  build_win:
    name: Windows
    runs-on: windows-2019
    needs: [check_changelog, setup_release]

    steps:
      - name: Checkout
        uses: actions/checkout@v3
        with:
          submodules: recursive

      - name: Setup Dependencies Windows
        uses: msys2/setup-msys2@v2
        with:
          update: true
          install: >-
            base-devel
            diffutils
            git
            make
            mingw-w64-x86_64-binutils
            mingw-w64-x86_64-boost
            mingw-w64-x86_64-cmake
            mingw-w64-x86_64-curl
            mingw-w64-x86_64-libmfx
            mingw-w64-x86_64-nsis
            mingw-w64-x86_64-openssl
            mingw-w64-x86_64-opus
            mingw-w64-x86_64-toolchain
            nasm
            wget
            yasm

      - name: Install npm packages
        run: |
          npm install

      - name: Build Windows
        shell: msys2 {0}
        env:
          BRANCH: ${{ github.head_ref || github.ref_name }}
          BUILD_VERSION: ${{ needs.check_changelog.outputs.next_version_bare }}
          COMMIT: ${{ github.event.pull_request.head.sha || github.sha }}
        run: |
          mkdir build
          cd build
          cmake -DCMAKE_BUILD_TYPE=RelWithDebInfo \
            -DSUNSHINE_ASSETS_DIR=assets \
            -G "MinGW Makefiles" \
            ..
          mingw32-make -j$(nproc)

      - name: Package Windows
        shell: msys2 {0}
        run: |
          mkdir -p artifacts
          cd build

          # package
          cpack -G NSIS
          cpack -G ZIP

          # move
          mv ./cpack_artifacts/Sunshine.exe ../artifacts/sunshine-windows-installer.exe
          mv ./cpack_artifacts/Sunshine.zip ../artifacts/sunshine-windows-portable.zip

      - name: Package Windows Debug Info
        working-directory: build
        run: |
          # save the original binaries with debug info
          7z -r `
            "-xr!CMakeFiles" `
            "-xr!cpack_artifacts" `
            a "../artifacts/sunshine-debuginfo-win32.zip" "*.exe"

      - name: Upload Artifacts
        uses: actions/upload-artifact@v3
        with:
          name: sunshine-windows
          path: artifacts/

      - name: Create/Update GitHub Release
        if: ${{ needs.setup_release.outputs.create_release == 'true' }}
        uses: ncipollo/release-action@v1
        with:
          name: ${{ needs.setup_release.outputs.release_name }}
          tag: ${{ needs.setup_release.outputs.release_tag }}
          commit: ${{ needs.setup_release.outputs.release_commit }}
          artifacts: "*artifacts/*"
          token: ${{ secrets.GH_BOT_TOKEN }}
          allowUpdates: true
          body: ${{ needs.setup_release.outputs.release_body }}
          discussionCategory: announcements
          prerelease: ${{ needs.setup_release.outputs.pre_release }}

  release-winget:
    name: Release to WinGet
    needs: [setup_release, build_win]
    if: ${{ needs.setup_release.outputs.create_release == 'true' && github.ref == 'refs/heads/master' }}
    runs-on: windows-latest  # the required action can only be run on Windows
    steps:
      - name: Release to WinGet
        uses: vedantmgoyal2009/winget-releaser@v2
        with:
          identifier: LizardByte.Sunshine
          release-tag: ${{ needs.setup_release.outputs.release_tag }}
          installers-regex: '\.exe$'  # only .exe files
          token: ${{ secrets.GH_BOT_TOKEN }}
