name: "Build"

on:
  push:
    branches: [main]
    
jobs:
  analyze:
    name: Static code analysis
    runs-on: windows-latest
    steps:
      - name: Setup .NET
        uses: actions/setup-dotnet@v4
        with:
          dotnet-version: |
            6.0.x
            7.0.x
            8.0.x
      - name: Set up JDK 17
        uses: actions/setup-java@v4
        with:
          distribution: 'temurin'
          java-version: '17'
      - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4
        with:
          fetch-depth: 0  # Shallow clones should be disabled for a better relevancy of analysis
      - name: Cache SonarCloud packages
        uses: actions/cache@v4
        with:
          path: ~\sonar\cache
          key: ${{ runner.os }}-sonar
          restore-keys: ${{ runner.os }}-sonar
      - name: Cache SonarCloud scanner
        id: cache-sonar-scanner
        uses: actions/cache@v4
        with:
          path: .\.sonar\scanner
          key: ${{ runner.os }}-sonar-scanner
          restore-keys: ${{ runner.os }}-sonar-scanner
      - name: Install SonarCloud scanner
        if: steps.cache-sonar-scanner.outputs.cache-hit != 'true'
        shell: powershell
        run: |
          New-Item -Path .\.sonar\scanner -ItemType Directory
          dotnet tool update dotnet-sonarscanner --tool-path .\.sonar\scanner
      - name: Build and analyze
        env:
          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}  # Needed to get PR information, if any
          SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }}
        shell: powershell
        run: |
          dotnet tool install minver-cli --global
          dotnet tool restore
          $version = minver -t v
          $productVersion,$prerelease = $version -split '-',2
          echo "Detected product version: $productVersion"
          .\.sonar\scanner\dotnet-sonarscanner begin /k:"Testably_Testably.Abstractions" /o:"testably" /d:sonar.token="${{ secrets.SONAR_TOKEN }}" /d:sonar.host.url="https://sonarcloud.io" /v:"$productVersion" /d:sonar.cs.vscoveragexml.reportsPaths=coverage.xml
          dotnet tool install --global dotnet-coverage
          dotnet restore -s 'nuget.config'
          dotnet build --no-incremental /p:NetCoreOnly=True --configuration "Release"
          dotnet-coverage collect 'dotnet test --no-build' -f xml  -o 'coverage.xml' -s '.github\coverage-settings.xml'
          .\.sonar\scanner\dotnet-sonarscanner end /d:sonar.token="${{ secrets.SONAR_TOKEN }}"

  test-macos:
    name: Test (MacOS)
    runs-on: macos-latest
    steps:
      - name: Checkout sources
        uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4
        with:
          fetch-depth: 0
      - name: Setup .NET
        uses: actions/setup-dotnet@v4
        with:
          dotnet-version: |
            6.0.x
            7.0.x
            8.0.x
      - name: Build solution
        run: dotnet build /p:NetCoreOnly=True --configuration "Release"
      - name: Run tests
        uses: Wandalen/wretry.action@v1.4.4
        with:
          command: dotnet test --no-build --collect:"XPlat Code Coverage"
          attempt_limit: 2
      - name: Upload coverage
        uses: actions/upload-artifact@v3
        with:
          name: Code coverage (MacOS)
          path: "**/coverage.cobertura.xml"

  test-ubuntu:
    name: Test (Ubuntu)
    runs-on: ubuntu-latest
    steps:
      - name: Checkout sources
        uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4
        with:
          fetch-depth: 0
      - name: Setup .NET
        uses: actions/setup-dotnet@v4
        with:
          dotnet-version: |
            6.0.x
            7.0.x
            8.0.x
      - name: Build solution
        run: dotnet build /p:NetCoreOnly=True --configuration "Release"
      - name: Run tests
        uses: Wandalen/wretry.action@v1.4.4
        with:
          command: dotnet test --no-build --collect:"XPlat Code Coverage"
          attempt_limit: 2
      - name: Upload coverage
        uses: actions/upload-artifact@v3
        with:
          name: Code coverage (Ubuntu)
          path: "**/coverage.cobertura.xml"

  test-windows:
    name: Test (Windows)
    runs-on: windows-latest
    steps:
      - name: Checkout sources
        uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4
        with:
          fetch-depth: 0
      - name: Setup .NET
        uses: actions/setup-dotnet@v4
        with:
          dotnet-version: |
            6.0.x
            7.0.x
            8.0.x
      - name: Build solution
        run: dotnet build /p:NetCoreOnly=True --configuration "Release"
      - name: Run tests
        uses: Wandalen/wretry.action@v1.4.4
        with:
          command: dotnet test --no-build --collect:"XPlat Code Coverage"
          attempt_limit: 2
      - name: Upload coverage
        uses: actions/upload-artifact@v3
        with:
          name: Code coverage (Windows)
          path: "**/coverage.cobertura.xml"
        
  test-net-framework:
    name: Test (.NET Framework)
    runs-on: windows-latest
    steps:
      - name: Checkout sources
        uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4
        with:
          fetch-depth: 0
      - name: Setup .NET
        uses: actions/setup-dotnet@v4
        with:
          dotnet-version: |
            6.0.x
            7.0.x
            8.0.x
      - name: Setup MSBuild
        uses: microsoft/setup-msbuild@v2
      - name: Setup VSTest
        uses: darenm/Setup-VSTest@v1
      - name: Navigate to Workspace
        run: cd $GITHUB_WORKSPACE
      - name: Build solution
        run: msbuild.exe Testably.Abstractions.sln /p:NetFrameworkOnly=True /p:platform="Any CPU" /p:configuration="Release" -t:restore,build -p:RestorePackagesConfig=true
      - name: Run tests
        run: vstest.console.exe .\Build\Tests\Testably.Abstractions.Tests\net48\Testably.Abstractions.Tests.dll .\Build\Tests\Testably.Abstractions.Parity.Tests\net48\Testably.Abstractions.Parity.Tests.dll .\Build\Tests\Testably.Abstractions.Testing.Tests\net48\Testably.Abstractions.Testing.Tests.dll
        
  test-examples:
    name: Test (Examples)
    runs-on: windows-latest
    steps:
      - name: Checkout sources
        uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4
        with:
          fetch-depth: 0
      - name: Setup .NET
        uses: actions/setup-dotnet@v4
        with:
          dotnet-version: |
            6.0.x
            7.0.x
            8.0.x
      - name: Build solution
        run: dotnet build /p:NetCoreOnly=True --configuration "Release"
      - name: Build example solution
        run: dotnet build Examples /p:UseFileReferenceToTestablyLibraries=True
      - name: Run example tests
        uses: Wandalen/wretry.action@v1.4.4
        with:
          command: dotnet test Examples --no-build
          attempt_limit: 2

  upload-coverage:
    name: Upload coverage to Codacy
    needs: [test-macos, test-ubuntu, test-windows, test-net-framework]
    runs-on: ubuntu-latest
    steps:
      - name: Checkout sources
        uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4
        with:
          fetch-depth: 0
      - name: Download code coverage files (MacOS)
        uses: actions/download-artifact@v3
        with:
          name: Code coverage (MacOS)
          path: Coverage/MacOS
      - name: Download code coverage files (Ubuntu)
        uses: actions/download-artifact@v3
        with:
          name: Code coverage (Ubuntu)
          path: Coverage/Ubuntu
      - name: Download code coverage files (Windows)
        uses: actions/download-artifact@v3
        with:
          name: Code coverage (Windows)
          path: Coverage/Windows
      - name: Generate coverage report
        uses: danielpalme/ReportGenerator-GitHub-Action@5.2.2
        with:
          reports: "Coverage/**/coverage.cobertura.xml"
          targetdir: "coverage-report"
          reporttypes: "Cobertura"
      - name: Publish coverage report to Codacy
        uses: codacy/codacy-coverage-reporter-action@master
        with:
          project-token: ${{ secrets.CODACY_PROJECT_TOKEN }}
          coverage-reports: coverage-report/Cobertura.xml