name: 🐧 Linux Builds

# Controls when the action will run. Triggers the workflow on push or pull request
# events but only for the master branch
on:
  push:
    branches:
      - master
    tags:
      - v*
  pull_request:
    branches:
      - master
    paths-ignore:
      - "**/*.md"
      - "**/*.bat"
      - "**/*.cmd"
      - "**/*.props"
      - "**/*.sln"
      - ".clang-format"
      - ".codacy.yaml"
      - ".github/*"
      - ".github/workflows/lint-gamedb.yml"
      - ".github/workflows/macos-workflow.yml"
      - ".github/workflows/pr-triage.yml"
      - ".github/workflows/scripts/windows/**"
      - ".github/workflows/scripts/validation/**"
      - ".github/workflows/windows-workflow.yml"
      - ".gitignore"
      - "bin/PCSX2_keys.ini.default"
      - "build.sh"
      - "buildbot.xml"
      - "pcsx2/CDVD/Windows/**"
      - "pcsx2/DEV9/Win32/**"
      - "pcsx2/PAD/Windows/**"
      - "pcsx2/SPU2/Windows/**"
      - "pcsx2/USB/Win32/**"
      - "pcsx2/windows/**"

jobs:
  build:
    strategy:
      # Prevent one build from failing everything (although maybe those should be included as experimental builds instead)
      fail-fast: false
      matrix:
        include:
          - os: ubuntu-18.04
            platform: x64
            compiler: gcc
            cmakeflags: -DLTO_PCSX2_CORE=ON
            appimage: true
            experimental: false
          - os: ubuntu-18.04
            platform: x64
            compiler: clang
            # Need to disable PCH until cmake 3.17
            # (PCH conflicts with ccache, fixed by https://gitlab.kitware.com/cmake/cmake/-/merge_requests/4400)
            cmakeflags: -DCMAKE_DISABLE_PRECOMPILE_HEADERS=ON
            detail: " nopch"
            appimage: false
            experimental: false
          - os: ubuntu-18.04
            platform: x64
            compiler: gcc
            cmakeflags: -DCMAKE_DISABLE_PRECOMPILE_HEADERS=ON
            detail: " nopch"
            appimage: false
            experimental: false
          - os: ubuntu-18.04
            platform: x64
            compiler: gcc
            cmakeflags: -DCMAKE_DISABLE_PRECOMPILE_HEADERS=ON -DARCH_FLAG=-march=haswell
            detail: " avx2 nopch"
            appimage: false
            experimental: false

    name: ${{ matrix.compiler }}${{ matrix.detail }}
    runs-on: ${{ matrix.os }}
    continue-on-error: ${{ matrix.experimental }}
    # Set some sort of timeout in the event of run-away builds.  We are limited on concurrent jobs so, get rid of them.
    timeout-minutes: 60

    env:
      CCACHE_BASEDIR: ${{ github.workspace }}
      CCACHE_DIR: ${{ github.workspace }}/.ccache
      CCACHE_COMPRESS: true
      CCACHE_COMPRESSLEVEL: 9
      CCACHE_MAXSIZE: 100M
      SDL: SDL2-2.0.16
      PATCHELF_VERSION: 0.12

    steps:
      # NOTE - useful for debugging
      # - name: Dump GitHub context
      #   env:
      #     GITHUB_CONTEXT: ${{ toJson(github) }}
      #   run: |
      #     echo "$GITHUB_CONTEXT"
      #     echo ${{ github.event.pull_request.title }}

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

      - name: Checkout Submodules
        if: steps.cache-submodules.outputs.cache-hit != 'true'
        run: git submodule update --init --recursive -j $(getconf _NPROCESSORS_ONLN)

      # -- SETUP CCACHE - https://cristianadam.eu/20200113/speeding-up-c-plus-plus-github-actions-using-ccache/
      - name: Prepare ccache timestamp
        id: ccache_cache_timestamp
        shell: cmake -P {0}
        run: |
          string(TIMESTAMP current_date "%Y-%m-%d-%H;%M;%S" UTC)
          message("::set-output name=timestamp::${current_date}")

      - name: ccache cache files
        uses: actions/cache@v3
        with:
          path: .ccache
          key: ${{ matrix.os }} ${{ matrix.platform }} ${{ matrix.compiler }}${{ matrix.detail }} ccache ${{ steps.ccache_cache_timestamp.outputs.timestamp }}
          restore-keys: ${{ matrix.os }} ${{ matrix.platform }} ${{ matrix.compiler }}${{ matrix.detail }} ccache

      - name: Prepare Artifact Metadata
        id: artifact-metadata
        shell: bash
        run: |
          ARCH=$([ "${{ matrix.platform }}" == x86 ] && echo "32bit" || echo "64bit")
          ARTIFACT_NAME=""
          if [ ${{ github.event_name }} == "pull_request" ]; then
            PR_SHA=$(git rev-parse --short "${{ github.event.pull_request.head.sha }}")
            ARTIFACT_NAME="PCSX2-${ARCH}"
            if [ ! -z "${{ github.event.pull_request.number }}" ]; then
              PR_NUM=${{ github.event.pull_request.number }}
              ARTIFACT_NAME="${ARTIFACT_NAME}-pr[${PR_NUM}]"
            fi
            ARTIFACT_NAME="${ARTIFACT_NAME}-sha[${PR_SHA}]"
            if [ ! -z "${{ github.event.pull_request.title }}" ]; then
              PR_TITLE=$(echo "${{ github.event.pull_request.title }}" | tr -cd '[a-zA-Z0-9[:space:]]_-')
              ARTIFACT_NAME="${ARTIFACT_NAME}-title["${PR_TITLE}""
            fi
          else
            SHA=$(git rev-parse --short "$GITHUB_SHA")
            ARTIFACT_NAME="PCSX2-${ARCH}-sha[${SHA}"
          fi
          TRIMMED_ARTIFACT_NAME=$(printf "%.199s]" "$ARTIFACT_NAME")
          echo "name=$TRIMMED_ARTIFACT_NAME"
          echo "##[set-output name=name;]${TRIMMED_ARTIFACT_NAME}"
          echo "##[set-output name=arch;]${ARCH}"

      - name: Install Packages
        env:
          PLATFORM: ${{ matrix.platform }}
          COMPILER: ${{ matrix.compiler }}
        run: .github/workflows/scripts/linux/install-packages.sh

      - name: Cache Dependencies
        uses: actions/cache@v3
        with:
          path: |
            3rdparty/${{ env.SDL }}
            3rdparty/patchelf-${{ env.PATCHELF_VERSION }}
          key: ${{ matrix.os }} ${{ matrix.platform }} ${{ env.SDL }} patchelf-${{ env.PATCHELF_VERSION }}

      - name: Build Dependencies
        run: |
          if [[ ! -e 3rdparty/patchelf-${{ env.PATCHELF_VERSION }} ]]; then
            curl -sSfL https://github.com/NixOS/patchelf/releases/download/${{ env.PATCHELF_VERSION }}/patchelf-${{ env.PATCHELF_VERSION }}.tar.bz2 | tar -xjC 3rdparty
            mv 3rdparty/patchelf-${{ env.PATCHELF_VERSION }}* 3rdparty/patchelf-${{ env.PATCHELF_VERSION }}
            cd 3rdparty/patchelf-${{ env.PATCHELF_VERSION }}
            ./configure
            make && cd ../../
          fi
          sudo make -C 3rdparty/patchelf-${{ env.PATCHELF_VERSION }} install
          if [[ ! -e 3rdparty/${{ env.SDL }} ]]; then
            curl -sL https://libsdl.org/release/${{ env.SDL }}.tar.gz | tar -xzC 3rdparty
            cd 3rdparty/${{ env.SDL }}
            if [ "${{ matrix.platform }}" == "x86" ]; then
              ./configure --build=i686-pc-linux-gnu CC=${{ matrix.compiler }} CFLAGS=-m32 CXXFLAGS=-m32 LDFLAGS=-m32 --prefix=/usr --libdir=/usr/lib/i386-linux-gnu
            else
              ./configure --prefix=/usr --libdir=/usr/lib/x86_64-linux-gnu
            fi
            make -j $(getconf _NPROCESSORS_ONLN) && cd ../../
          fi
          sudo make -C 3rdparty/${{ env.SDL }} install

      - name: Generate CMake
        env:
          PLATFORM: ${{ matrix.platform }}
          COMPILER: ${{ matrix.compiler }}
          ADDITIONAL_CMAKE_ARGS: ${{ matrix.cmakeflags }}
        run: .github/workflows/scripts/linux/generate-cmake.sh

      - name: Build PCSX2
        working-directory: build
        run: ../.github/workflows/scripts/linux/compile.sh

      - name: Run Tests
        working-directory: ./build
        run: ninja unittests

      - name: Package AppImage
        if: matrix.appimage == true
        env:
          PLATFORM: ${{ matrix.platform }}
          COMPILER: ${{ matrix.compiler }}
          name: ${{ steps.artifact-metadata.outputs.name }}
        run: .github/workflows/scripts/linux/appimage.sh

      - name: Upload artifact
        if: matrix.appimage == true
        uses: actions/upload-artifact@v2
        with:
          name: ${{ steps.artifact-metadata.outputs.name }}
          path: ci-artifacts

      # ---- Release / Tagging related steps ----
      - name: Prepare Build Artifacts
        if: github.repository == 'PCSX2/pcsx2' && startsWith(github.ref, 'refs/tags/') && matrix.appimage == true
        run: |
          mv ./ci-artifacts/*.AppImage ./ci-artifacts/linux-AppImage-${{ steps.artifact-metadata.outputs.arch }}.AppImage
          ls ./ci-artifacts/

      - name: Upload Assets and Potential Publish Release
        if: github.repository == 'PCSX2/pcsx2' && startsWith(github.ref, 'refs/tags/') && matrix.appimage == true
        env:
          GITHUB_TOKEN: ${{ secrets.BOT_PAT }}
          ASSET_DIR: ${{ github.WORKSPACE }}/ci-artifacts
          ASSET_EXTENSION: AppImage
          TAG_TO_SEARCH_FOR: ${{ github.REF }}
        run: |
          cd ./.github/workflows/scripts/releases/upload-release-artifacts
          npm ci
          node index.js
