diff --git a/.github/workflows/check-xaml-formatting.yml b/.github/workflows/check-xaml-formatting.yml deleted file mode 100644 index 44b034176ff3..000000000000 --- a/.github/workflows/check-xaml-formatting.yml +++ /dev/null @@ -1,49 +0,0 @@ -name: Check XAML Formatting -on: - workflow_dispatch: - push: - branches: - - 'main' - - 'service/**' - paths: - - '**.xaml' - pull_request: - branches: - - 'main' - - 'service/**' - paths: - - '**.xaml' - -jobs: - check-formatting: - runs-on: ubuntu-latest - defaults: - run: - shell: pwsh - steps: - - uses: actions/checkout@v3 - with: - fetch-depth: 2 - - - name: Install Xaml Styler - run: | - dotnet tool install --global XamlStyler.Console - - - name: Check Formatting - id: check-step - run: | - $changedFiles = (git diff --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 job if necessary - if: steps.check-step.outcome == 'failure' - run: exit 1 - diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml new file mode 100644 index 000000000000..6d71c68f3d7c --- /dev/null +++ b/.github/workflows/ci.yml @@ -0,0 +1,241 @@ +# Copyright (c) 2023 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: + - 'specs/**' + - '*.md' + pull_request: + paths-ignore: + - 'specs/**' + - '*.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: + runs-on: ubuntu-latest + defaults: + run: + shell: pwsh + + steps: + + - name: Checkout the repository + uses: actions/checkout@v3 + with: + fetch-depth: 2 + + - name: Install XamlStyler console + run: 'dotnet tool install --global XamlStyler.Console' + + - name: Check XAML formatting + id: check-step + run: | + $changedFiles = (git diff --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 the job if the XamlStyler found unformatted file(s) + if: steps.check-step.outcome == 'failure' + run: exit 1 + + build: + 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@v3 + + - name: Setup MSBuild + uses: microsoft/setup-msbuild@v1 + + - name: Setup NuGet + uses: NuGet/setup-nuget@v1.1.1 + + - name: Setup .NET 7 + uses: actions/setup-dotnet@v3 + with: + dotnet-version: '7.0.x' + + - 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: ./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@v3 + with: + name: 'Appx Packages (${{ env.CONFIGURATION }}, ${{ env.ARCHITECTURE }})' + path: ${{ env.ARTIFACTS_STAGING_DIR }} + + test: + 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: + + - name: Checkout the repository + uses: actions/checkout@v3 + + - name: Download the packages from the Artifacts + uses: actions/download-artifact@v3 + 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" + + - name: Run interaction tests + run: | + 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' diff --git a/builds/Files_SelfSigned.pfx b/builds/Files_SelfSigned.pfx deleted file mode 100644 index ad8719910d5b..000000000000 Binary files a/builds/Files_SelfSigned.pfx and /dev/null differ diff --git a/builds/azure-pipelines.yml b/builds/azure-pipelines.yml deleted file mode 100644 index d117f2d60c12..000000000000 --- a/builds/azure-pipelines.yml +++ /dev/null @@ -1,122 +0,0 @@ -trigger: -- main - -pool: - vmImage: 'windows-latest' - -variables: - solution: '**/*.sln' - buildPlatform: 'x64' - buildConfiguration: 'Release' - appxPackageDir: '$(build.artifactStagingDirectory)\AppxPackages\\' - -steps: -- task: PowerShell@2 - inputs: - targetType: 'inline' - script: | - [xml]$xmlDoc = Get-Content '$(Build.SourcesDirectory)\src\Files.App (Package)\Package.appxmanifest' - $xmlDoc.Package.Identity.Name="49306atecsolution.FilesUWP" - $xmlDoc.Package.Identity.Publisher="CN=53EC4384-7F5B-4CF6-8C23-513FFE9D1AB7" - $xmlDoc.Package.Properties.DisplayName="Files" - $xmlDoc.Package.Applications.Application.VisualElements.DisplayName="Files" - $xmlDoc.Save('$(Build.SourcesDirectory)\src\Files.App (Package)\Package.appxmanifest') - failOnStderr: true - -- task: PowerShell@2 - displayName: 'Use Release Logo' - inputs: - targetType: 'inline' - script: | - gci $(Build.SourcesDirectory)\src -Include *.csproj, *.appxmanifest, *.wapproj -recurse | ForEach -Process { - (Get-Content $_ -Raw | ForEach -Process {$_ -replace "Assets\\AppTilesDev", "Assets\AppTiles"}) | Set-Content $_ -NoNewline - } - failOnStderr: true - -- task: DownloadSecureFile@1 - name: mapsDevKey - displayName: 'Download Bing Maps Dev Key' - inputs: - secureFile: 'BingMapsKey.txt' - -- task: CopyFiles@2 - inputs: - SourceFolder: '$(Agent.TempDirectory)' - Contents: '$(mapsDevKey.secureFilePath)' - TargetFolder: '$(Build.SourcesDirectory)\src\Files.App\Resources' - overWrite: true - -- task: UseDotNet@2 - inputs: - packageType: sdk - version: 7.0.x - includePreviewVersions: true - -- task: CmdLine@2 - inputs: - script: | - for /f %%a in ('dir /b /a:d %localappdata%\Microsoft\VisualStudio\17*') do echo UsePreviews=True>%localappdata%\Microsoft\VisualStudio\%%a\sdk.txt - -- task: MSBuild@1 - inputs: - platform: 'x64' - solution: '**/*.sln' - configuration: '$(buildConfiguration)' - msbuildArguments: '/t:restore /p:Configuration=Debug;Platform="$(buildPlatform)";PublishReadyToRun=true' - maximumCpuCount: true - -- task: MSBuild@1 - inputs: - platform: 'x64' - solution: '**/*.wapproj' - configuration: '$(buildConfiguration)' - msbuildArguments: '/t:build;_GenerateAppxPackage /p:Configuration=Debug;Platform="$(buildPlatform)";AppxBundle=Always;AppxBundlePlatforms="$(buildPlatform)";AppxPackageDir="$(appxPackageDir)";AppxPackageSigningEnabled=true;UapAppxPackageBuildMode=SideloadOnly;PackageCertificateKeyFile="$(Build.SourcesDirectory)\builds\Files_SelfSigned.pfx";PackageCertificatePassword="";PackageCertificateThumbprint=""' - maximumCpuCount: true - -- task: DotNetCoreCLI@2 - inputs: - command: 'build' - arguments: './tests/Files.InteractionTests/Files.InteractionTests.csproj --configuration $(buildConfiguration)' - -- task: PowerShell@2 - inputs: - targetType: 'inline' - script: | - # Find correct folder and run app install script. - cd $(appxPackageDir) - - $AppBundle = Get-ChildItem -Filter Files*Test -Name - echo $AppBundle - cd $AppBundle - ./Install.ps1 -Force - Get-AppxPackage - errorActionPreference: 'continue' - failOnStderr: true - workingDirectory: '$(System.DefaultWorkingDirectory)' - - -- task: Windows Application Driver@0 - inputs: - OperationType: 'Start' - AgentResolution: '1080p' - -- task: VSTest@2 - inputs: - testSelector: 'testAssemblies' - testAssemblyVer2: | - **\*Files.InteractionTests.dll - !**\*TestAdapter.dll - !**\obj\** - searchFolder: '$(System.DefaultWorkingDirectory)' - -- task: CopyFiles@2 - displayName: 'Copy Files to: $(build.artifactstagingdirectory)' - inputs: - SourceFolder: '$(system.defaultworkingdirectory)' - Contents: '**\bin\$(BuildConfiguration)\**' - TargetFolder: '$(build.artifactstagingdirectory)' - -- task: PublishBuildArtifacts@1 - displayName: 'Publish Artifact: drop' - inputs: - PathtoPublish: '$(build.artifactstagingdirectory)' diff --git a/scripts/Convert-TrxToMarkdown.ps1 b/scripts/Convert-TrxToMarkdown.ps1 new file mode 100644 index 000000000000..3c21ebf14dde --- /dev/null +++ b/scripts/Convert-TrxToMarkdown.ps1 @@ -0,0 +1,219 @@ +# Copyright (c) 2023 Files Community +# Licensed under the MIT License. See the LICENSE. + +# Abstract: +# This script analyzes the trx file that is the result of executing dotnet test and +# converts it to markdown, which is used for the Files CI. + +using namespace System.Collections.Generic; +using namespace System.Linq; + +param( + [string]$Source = "", + [string]$Destination = "" +) + +class Trx +{ + [ResultSummary] $ResultSummary + [TrxTimes] $Times + [TrxTestDefinition[]]$TestDefinitions + [TrxUnitTestResult[]]$Results + + Trx() + { + $this.Times = New-Object TrxTimes + $this.ResultSummary = New-Object ResultSummary + } +} + +class ResultSummary +{ + [int] $total + [int] $passed + [int] $failed +} + +class TrxTimes +{ + [Datetime] $creation + [Datetime] $queuing + [Datetime] $start + [Datetime] $finish +} + +class TrxTestDefinition +{ + [string] $id + [string] $name + [string] $className +} + +class TrxUnitTestResult +{ + [string] $id + [string] $result + [string] $name + [string] $errorMessage + [string] $errorStackTrace +} + +[xml]$xmlDoc = Get-Content $Source + +$trxObject = New-Object Trx + +# Result summary +$trxObject.ResultSummary.total = $xmlDoc.TestRun.ResultSummary.Counters.total +$trxObject.ResultSummary.passed = $xmlDoc.TestRun.ResultSummary.Counters.passed +$trxObject.ResultSummary.failed = $xmlDoc.TestRun.ResultSummary.Counters.failed + +# Times +$trxObject.Times.start = $xmlDoc.TestRun.Times.start +$trxObject.Times.finish = $xmlDoc.TestRun.Times.finish + +# Unit test definitions +foreach ($item in $xmlDoc.TestRun.TestDefinitions.UnitTest) +{ + $newOne = [TrxTestDefinition]::new() + + $newOne.id = $item.Execution.id + $newOne.name = $item.name + $newOne.className = $item.TestMethod.className + + $trxObject.TestDefinitions += $newOne +} + +# Unit tests +foreach ($item in $xmlDoc.TestRun.Results.UnitTestResult) +{ + $newOne = [TrxUnitTestResult]::new() + + $newOne.id = $item.executionId + $newOne.result = $item.outcome + $newOne.name = $item.testName + $newOne.errorMessage = $item.Output.ErrorInfo.Message + $newOne.errorStackTrace = $item.Output.ErrorInfo.StackTrace + + $trxObject.Results += $newOne +} + +$stringBuilder = New-Object System.Text.StringBuilder + +$title = "## Tested with Files " +$AbbreviatedOid = $env:GITHUB_SHA +$AbbreviatedOid = $AbbreviatedOid.Substring(0, 7) +$resultOverview = "" + +# Header +[void]$stringBuilder.AppendLine($title); +[void]$stringBuilder.AppendLine(""); + +$skippedIcon = "⏩" +$passedIcon = "✅" +$failedIcon = "❌" +$unknownIcon = "⚠️" + +# Skipped +if ($trxObject.ResultSummary.failed -ne 0 -and $trxObject.ResultSummary.passed -ne 0) +{ + $resultOverview = $partialSuccessfulfulIcon + "Some tests were not successful" +} +# Passed +elseif ($trxObject.ResultSummary.failed -eq 0) +{ + $resultOverview = $passedIcon + " All tests have passed" +} +# Failed +elseif ($trxObject.ResultSummary.failed -ne 0 -and $trxObject.ResultSummary.passed -eq 0) +{ + $resultOverview = $failedIcon + " All tests have failed" +} +else +{ + $resultOverview = $unknownIcon + " Unknown result" +} + +# Overview table +[void]$stringBuilder.AppendLine("
Commit: | "); +[void]$stringBuilder.AppendLine("$AbbreviatedOid | ");
+[void]$stringBuilder.AppendLine("
Status: | "); +[void]$stringBuilder.AppendLine("$resultOverview | "); +[void]$stringBuilder.AppendLine("
Full log: | "); +[void]$stringBuilder.AppendLine("https://github.com/files-community/Files/actions/runs/$GITHUB_RUN_ID/job/$GITHUB_JOB | "); +[void]$stringBuilder.AppendLine("
" + $baseClassName.className + "." + $item.name + "
"
+ }
+
+ [void]$stringBuilder.AppendLine("$testName`|$resultStatus`|$failedClassName");
+
+ $index++
+}
+
+[void]$stringBuilder.AppendLine("");
+
+[void]$stringBuilder.AppendLine("