on: [push, pull_request]
name: Continuous Integration

jobs:
  inspect-code:
    name: Code Quality
    runs-on: ubuntu-latest
    steps:
      - name: Checkout
        uses: actions/checkout@v2

      # FIXME: Tools won't run in .NET 6.0 unless you install 3.1.x LTS side by side.
      # https://itnext.io/how-to-support-multiple-net-sdks-in-github-actions-workflows-b988daa884e
      - name: Install .NET 3.1.x LTS
        uses: actions/setup-dotnet@v1
        with:
          dotnet-version: "3.1.x"

      - name: Install .NET 6.0.x
        uses: actions/setup-dotnet@v1
        with:
          dotnet-version: "6.0.x"

      - name: Restore Tools
        run: dotnet tool restore

      - name: Restore Packages
        run: dotnet restore

      - name: Restore inspectcode cache
        uses: actions/cache@v3
        with:
          path: ${{ github.workspace }}/inspectcode
          key: inspectcode-${{ hashFiles('.config/dotnet-tools.json', '.github/workflows/ci.yml', 'osu.sln*', '.editorconfig', '.globalconfig', 'CodeAnalysis/*') }}

      - name: Dotnet code style
        run: dotnet build -c Debug -warnaserror osu.Desktop.slnf -p:EnforceCodeStyleInBuild=true

      - name: CodeFileSanity
        run: |
          # TODO: Add ignore filters and GitHub Workflow Command Reporting in CFS. That way we don't have to do this workaround.
          # FIXME: Suppress warnings from templates project
          exit_code=0
          while read -r line; do
            if [[ ! -z "$line" ]]; then
              echo "::error::$line"
              exit_code=1
            fi
          done <<< $(dotnet codefilesanity)
          exit $exit_code

      - name: InspectCode
        run: dotnet jb inspectcode $(pwd)/osu.Desktop.slnf --no-build --output="inspectcodereport.xml" --caches-home="inspectcode" --verbosity=WARN

      - name: NVika
        run: dotnet nvika parsereport "${{github.workspace}}/inspectcodereport.xml" --treatwarningsaserrors

  test:
    name: Test
    runs-on: ${{matrix.os.fullname}}
    env:
      OSU_EXECUTION_MODE: ${{matrix.threadingMode}}
    strategy:
       fail-fast: false
       matrix:
          os:
            - { prettyname: Windows, fullname: windows-latest }
            - { prettyname: macOS, fullname: macos-latest }
            - { prettyname: Linux, fullname: ubuntu-latest }
          threadingMode: ['SingleThread', 'MultiThreaded']
    timeout-minutes: 60
    steps:
      - name: Checkout
        uses: actions/checkout@v2

      - name: Install .NET 6.0.x
        uses: actions/setup-dotnet@v1
        with:
          dotnet-version: "6.0.x"

      - name: Compile
        run: dotnet build -c Debug -warnaserror osu.Desktop.slnf

      - name: Test
        run: dotnet test $pwd/*.Tests/bin/Debug/*/*.Tests.dll --logger "trx;LogFileName=TestResults-${{matrix.os.prettyname}}-${{matrix.threadingMode}}.trx"
        shell: pwsh

      # Attempt to upload results even if test fails.
      # https://docs.github.com/en/actions/reference/context-and-expression-syntax-for-github-actions#always
      - name: Upload Test Results
        uses: actions/upload-artifact@v2
        if: ${{ always() }}
        with:
          name: osu-test-results-${{matrix.os.prettyname}}-${{matrix.threadingMode}}
          path: ${{github.workspace}}/TestResults/TestResults-${{matrix.os.prettyname}}-${{matrix.threadingMode}}.trx

  build-only-android:
    name: Build only (Android)
    runs-on: macos-latest
    timeout-minutes: 60
    steps:
      - name: Checkout
        uses: actions/checkout@v2

      # Pin Xamarin.Android version to 11.2 for now to avoid build failures caused by a Xamarin-side regression.
      # See: https://github.com/xamarin/xamarin-android/issues/6284
      # This can be removed/reverted when the fix makes it to upstream and is deployed on github runners.
      - name: Set default Xamarin SDK version
        run: |
            $VM_ASSETS/select-xamarin-sdk-v2.sh --mono=6.12 --android=11.2

      - name: Install .NET 6.0.x
        uses: actions/setup-dotnet@v1
        with:
          dotnet-version: "6.0.x"

      # Contrary to seemingly any other msbuild, msbuild running on macOS/Mono
      # cannot accept .sln(f) files as arguments.
      # Build just the main game for now.
      - name: Build
        run: msbuild osu.Android/osu.Android.csproj /restore /p:Configuration=Debug

  build-only-ios:
    name: Build only (iOS)
    runs-on: macos-latest
    timeout-minutes: 60
    steps:
      - name: Checkout
        uses: actions/checkout@v2

      - name: Install .NET 6.0.x
        uses: actions/setup-dotnet@v1
        with:
          dotnet-version: "6.0.x"

      # Contrary to seemingly any other msbuild, msbuild running on macOS/Mono
      # cannot accept .sln(f) files as arguments.
      # Build just the main game for now.
      - name: Build
        run: msbuild osu.iOS/osu.iOS.csproj /restore /p:Configuration=Debug