# Copyright (c) 2024 Files Community
# Licensed under the MIT License. See the LICENSE.

# Abstract:
#   This CI is executed when a new commit is created on the main branch or
#   on a PR whose head branch is the main branch.
#   However, the CI will not be executed if files not directly related to
#   source code maintenance are updated.

name: Files CI

on:
  push:
    branches:
      - main
    paths-ignore:
      - 'assets/**'
      - 'builds/**'
      - 'docs/**'
      - '*.md'
  pull_request:
    paths-ignore:
      - 'assets/**'
      - 'builds/**'
      - 'docs/**'
      - '*.md'

run-name: ${{ github.event_name == 'pull_request' && 'Files PR Validation' || 'Files CI Validation' }}

env:
  WORKING_DIR: ${{ github.workspace }} # Default: 'D:\a\Files\Files'
  SOLUTION_PATH: '${{ github.workspace }}\Files.sln'
  PACKAGE_PROJECT_DIR: '${{ github.workspace }}\src\Files.App (Package)'
  PACKAGE_PROJECT_PATH: '${{ github.workspace }}\src\Files.App (Package)\Files.Package.wapproj'
  AUTOMATED_TESTS_ARCHITECTURE: 'x64'
  AUTOMATED_TESTS_CONFIGURATION: 'Release'
  AUTOMATED_TESTS_PROJECT_DIR: '${{ github.workspace }}\tests\Files.InteractionTests'
  AUTOMATED_TESTS_PROJECT_PATH: '${{ github.workspace }}\tests\Files.InteractionTests\Files.InteractionTests.csproj'
  AUTOMATED_TESTS_ASSEMBLY_DIR: '${{ github.workspace }}\artifacts\TestsAssembly'
  ARTIFACTS_STAGING_DIR:  '${{ github.workspace }}\artifacts'
  APPX_PACKAGE_DIR: '${{ github.workspace }}\artifacts\AppxPackages'
  APPX_SELFSIGNED_CERT_PATH: '${{ github.workspace }}\.github\workflows\FilesApp_SelfSigned.pfx'
  WINAPPDRIVER_EXE86_PATH: 'C:\Program Files (x86)\Windows Application Driver\WinAppDriver.exe'
  WINAPPDRIVER_EXE64_PATH: 'C:\Program Files\Windows Application Driver\WinAppDriver.exe'

jobs:

  check-formatting:

    if: github.repository_owner == 'files-community'

    runs-on: windows-latest

    steps:

    - name: Checkout the repository
      uses: actions/checkout@v4
      with:
        fetch-depth: 2
    - name: Setup .NET 8
      uses: actions/setup-dotnet@v4

    - name: Install XamlStyler.Console
      run: 'dotnet tool install --global XamlStyler.Console'

    - name: Check XAML formatting
      id: check-step
      run: |
        $changedFiles = (git diff --diff-filter=d --name-only HEAD~1) -split "\n" | Where-Object {$_ -like "*.xaml"}
        foreach ($file in $changedFiles)
        {
          xstyler -p -l None -f $file
          if ($LASTEXITCODE -ne 0)
          {
            echo "::error file=$file::Format check failed"
          }
        }
      continue-on-error: true
    
    - name: Fail if necessary
      if: steps.check-step.outcome == 'failure'
      run: exit 1

  build:

    if: github.repository_owner == 'files-community'

    runs-on: windows-latest
    strategy:
      fail-fast: false
      matrix:
        configuration: [Debug, Release]
        platform: [x64, arm64]
    env:
      CONFIGURATION: ${{ matrix.configuration }}
      ARCHITECTURE: ${{ matrix.platform }}

    steps:

    - name: Checkout the repository
      uses: actions/checkout@v4
    - name: Setup MSBuild
      uses: microsoft/setup-msbuild@v2
    - name: Setup NuGet
      uses: NuGet/setup-nuget@v2
    - name: Setup .NET 8
      uses: actions/setup-dotnet@v4
      with:
        global-json-file: global.json

    - name: Restore NuGet
      shell: pwsh
      run: 'nuget restore $env:SOLUTION_PATH'

    - name: Restore Files
      shell: pwsh
      run: |
        msbuild $env:SOLUTION_PATH `
          -t:Restore `
          -p:Platform=$env:ARCHITECTURE `
          -p:Configuration=$env:CONFIGURATION `
          -p:PublishReadyToRun=true

    - if: env.CONFIGURATION != env.AUTOMATED_TESTS_CONFIGURATION || env.ARCHITECTURE != env.AUTOMATED_TESTS_ARCHITECTURE 
      name: Build Files
      run: |
        msbuild `
          $env:PACKAGE_PROJECT_PATH `
          -t:Build `
          -clp:ErrorsOnly `
          -p:Configuration=$env:CONFIGURATION `
          -p:Platform=$env:ARCHITECTURE `
          -p:AppxBundle=Never

    - if: env.CONFIGURATION == env.AUTOMATED_TESTS_CONFIGURATION && env.ARCHITECTURE == env.AUTOMATED_TESTS_ARCHITECTURE
      name: Create self signed cert as a pfx file
      run: ./.github/scripts/Generate-SelfCertPfx.ps1 -Destination "$env:APPX_SELFSIGNED_CERT_PATH"

    - if: env.CONFIGURATION == env.AUTOMATED_TESTS_CONFIGURATION && env.ARCHITECTURE == env.AUTOMATED_TESTS_ARCHITECTURE
      name: Build & package Files
      run: |
        msbuild `
          $env:PACKAGE_PROJECT_PATH `
          -t:Build `
          -t:_GenerateAppxPackage `
          -clp:ErrorsOnly `
          -p:Configuration=$env:CONFIGURATION `
          -p:Platform=$env:ARCHITECTURE `
          -p:AppxBundlePlatforms=$env:AUTOMATED_TESTS_ARCHITECTURE `
          -p:AppxBundle=Always `
          -p:UapAppxPackageBuildMode=SideloadOnly `
          -p:AppxPackageDir=$env:APPX_PACKAGE_DIR `
          -p:AppxPackageSigningEnabled=true `
          -p:PackageCertificateKeyFile=$env:APPX_SELFSIGNED_CERT_PATH `
          -p:PackageCertificatePassword="" `
          -p:PackageCertificateThumbprint=""

    - if: env.ARCHITECTURE == env.AUTOMATED_TESTS_ARCHITECTURE && env.CONFIGURATION == env.AUTOMATED_TESTS_CONFIGURATION
      name: Build interaction tests
      run: |
        msbuild $env:AUTOMATED_TESTS_PROJECT_PATH `
          -t:Build `
          -clp:ErrorsOnly `
          -p:Configuration=$env:CONFIGURATION `
          -p:Platform=$env:AUTOMATED_TESTS_ARCHITECTURE

    - if: env.ARCHITECTURE == env.AUTOMATED_TESTS_ARCHITECTURE && env.CONFIGURATION == env.AUTOMATED_TESTS_CONFIGURATION
      name: Copy tests bin to the artifacts dir
      shell: pwsh
      run: |
        Copy-Item `
          -Path "$env:AUTOMATED_TESTS_PROJECT_DIR\bin" `
          -Destination "$env:AUTOMATED_TESTS_ASSEMBLY_DIR" -Recurse

    - if: env.ARCHITECTURE == env.AUTOMATED_TESTS_ARCHITECTURE && env.CONFIGURATION == env.AUTOMATED_TESTS_CONFIGURATION
      name: Upload the packages to the Artifacts
      uses: actions/upload-artifact@v4
      with:
        name: 'Appx Packages (${{ env.CONFIGURATION }}, ${{ env.ARCHITECTURE }})'
        path: ${{ env.ARTIFACTS_STAGING_DIR }}

  test:

    if: github.repository_owner == 'files-community' && always()

    needs: [build]
    runs-on: windows-latest
    strategy:
      fail-fast: false
      matrix:
        configuration: [Release]
        platform: [x64]
    env:
      CONFIGURATION: ${{ matrix.configuration }}
    permissions:
      contents: read
      pull-requests: write

    steps:

    - if: contains(join(needs.*.result, ','), 'failure')
      name: Fail if necessary
      run: exit 1

    - name: Checkout the repository
      uses: actions/checkout@v4
    - name: Setup .NET 8
      uses: actions/setup-dotnet@v4
      with:
        global-json-file: global.json

    - name: Download the packages from the Artifacts
      uses: actions/download-artifact@v4
      with:
        name: 'Appx Packages (${{ env.CONFIGURATION }}, ${{ env.AUTOMATED_TESTS_ARCHITECTURE }})'
        path: ${{ env.ARTIFACTS_STAGING_DIR }}

    - name: Install Files
      shell: powershell
      run: |
        Set-Location "$env:APPX_PACKAGE_DIR"
        $AppxPackageBundleDir = Get-ChildItem -Filter Files.Package_*_Test -Name
        Set-Location $AppxPackageBundleDir
        ./Install.ps1 -Force
        Get-AppxPackage

    - name: Set full HD resolution
      run: Set-DisplayResolution -Width 1920 -Height 1080 -Force

    - name: Start WinAppDriver process
      shell: pwsh
      run: Start-Process -FilePath "$env:WINAPPDRIVER_EXE86_PATH"

    # Retry integration tests if first attempt fails
    - name: Run interaction tests
      uses: nick-fields/retry@v3
      with:
        timeout_minutes: 15
        max_attempts: 2
        shell: pwsh
        command: |
          dotnet test `
            $env:AUTOMATED_TESTS_ASSEMBLY_DIR\**\Files.InteractionTests.dll `
            --logger "trx;LogFileName=$env:AUTOMATED_TESTS_ASSEMBLY_DIR\testResults.trx"

    # - name: Generate markdown from the tests result
    #   shell: pwsh
    #   run: |
    #     . './scripts/Convert-TrxToMarkdown.ps1' `
    #       -Source "$env:AUTOMATED_TESTS_ASSEMBLY_DIR\testResults.trx" `
    #       -Destination "$env:AUTOMATED_TESTS_ASSEMBLY_DIR\testResults.md"
    #   env:
    #     PULL_REQUEST_ID: ${{ github.event.pull_request_id }}

    # - name: Display the markdown on the output (temp)
    #   shell: pwsh
    #   run: |
    #     Get-Content $env:AUTOMATED_TESTS_ASSEMBLY_DIR\testResults.md

    # - name: Publish tests result
    #   uses: marocchino/sticky-pull-request-comment@v2
    #   with:
    #     header: test-result
    #     path: '${{ env.AUTOMATED_TESTS_ASSEMBLY_DIR }}\testResults.md'
