From f0c4c8b82f25f77ebf1c2873af5859105dce6ec1 Mon Sep 17 00:00:00 2001 From: Andy Jordan <2226434+andyleejordan@users.noreply.github.com> Date: Wed, 6 Aug 2025 12:55:35 -0700 Subject: [PATCH] WIP: Modernizing CI --- .github/workflows/ci-test.yml | 50 ++++++++++++++++++++++++++++++ MockPSConsole/MockPSConsole.csproj | 6 ++-- PSReadLine.build.ps1 | 8 ++--- Polyfill/Polyfill.csproj | 6 ++-- README.md | 2 +- appveyor.yml | 26 ---------------- build.ps1 | 8 ++--- global.json | 7 +++++ nuget.config | 5 +-- test/ConsoleFixture.cs | 10 +++++- test/PSReadLine.Tests.csproj | 6 ++-- tools/helper.psm1 | 8 ++--- tools/installPSResources.ps1 | 20 ++++++++++++ 13 files changed, 108 insertions(+), 54 deletions(-) create mode 100644 .github/workflows/ci-test.yml delete mode 100644 appveyor.yml create mode 100644 global.json create mode 100644 tools/installPSResources.ps1 diff --git a/.github/workflows/ci-test.yml b/.github/workflows/ci-test.yml new file mode 100644 index 000000000..1c99a5c7f --- /dev/null +++ b/.github/workflows/ci-test.yml @@ -0,0 +1,50 @@ +name: CI Tests + +on: + push: + branches: [ master ] + pull_request: + branches: [ master ] + +jobs: + ci: + name: dotnet + strategy: + matrix: + os: [ windows-latest, macos-latest, ubuntu-latest ] + runs-on: ${{ matrix.os }} + env: + DOTNET_NOLOGO: true + DOTNET_GENERATE_ASPNET_CERTIFICATE: false + steps: + - name: Checkout repository + uses: actions/checkout@v4 + + - name: Install dotnet + uses: actions/setup-dotnet@v4 + with: + cache: true + cache-dependency-path: '**/*.csproj' + global-json-file: ./global.json + + - name: Install PSResources + shell: pwsh + run: ./tools/installPSResources.ps1 + + - name: Build, test, and package + shell: pwsh + run: Invoke-Build -Configuration Release -TestFramework net8.0 RunTests, ZipRelease + + - name: Upload build artifacts + if: always() + uses: actions/upload-artifact@v4 + with: + name: PSReadLine-module-${{ matrix.os }} + path: bin/Release/PSReadLine.zip + + - name: Upload test results + uses: actions/upload-artifact@v4 + if: always() + with: + name: PSReadLine-test-results-${{ matrix.os }} + path: test/TestResults/xUnitTestResults.en-US.xml diff --git a/MockPSConsole/MockPSConsole.csproj b/MockPSConsole/MockPSConsole.csproj index cebd3941d..351d5ed2d 100644 --- a/MockPSConsole/MockPSConsole.csproj +++ b/MockPSConsole/MockPSConsole.csproj @@ -4,7 +4,7 @@ Exe MockPSConsole MockPSConsole - net472;net6.0 + net472;net8.0 512 Program.manifest true @@ -14,8 +14,8 @@ - - + + diff --git a/PSReadLine.build.ps1 b/PSReadLine.build.ps1 index e245dfae3..ba917946c 100644 --- a/PSReadLine.build.ps1 +++ b/PSReadLine.build.ps1 @@ -19,7 +19,7 @@ param( [ValidateSet("Debug", "Release")] [string]$Configuration = (property Configuration Release), - [ValidateSet("net472", "net6.0")] + [ValidateSet("net472", "net8.0")] [string]$TestFramework, [switch]$CheckHelpContent @@ -31,7 +31,7 @@ Import-Module "$PSScriptRoot/tools/helper.psm1" $targetDir = "bin/$Configuration/PSReadLine" if (-not $TestFramework) { - $TestFramework = $IsWindows ? "net472" : "net6.0" + $TestFramework = $IsWindows ? "net472" : "net8.0" } function ConvertTo-CRLF([string] $text) { @@ -58,7 +58,7 @@ Synopsis: Build the Polyfiller assembly #> task BuildPolyfiller @polyFillerParams { exec { dotnet publish -c $Configuration -f 'netstandard2.0' Polyfill } - exec { dotnet publish -c $Configuration -f 'net6.0' Polyfill } + exec { dotnet publish -c $Configuration -f 'net8.0' Polyfill } } <# @@ -123,7 +123,7 @@ task LayoutModule BuildPolyfiller, BuildMainModule, { } Copy-Item "Polyfill/bin/$Configuration/netstandard2.0/Microsoft.PowerShell.PSReadLine.Polyfiller.dll" "$targetDir/netstd" -Force - Copy-Item "Polyfill/bin/$Configuration/net6.0/Microsoft.PowerShell.PSReadLine.Polyfiller.dll" "$targetDir/net6plus" -Force + Copy-Item "Polyfill/bin/$Configuration/net8.0/Microsoft.PowerShell.PSReadLine.Polyfiller.dll" "$targetDir/net6plus" -Force $binPath = "PSReadLine/bin/$Configuration/netstandard2.0/publish" Copy-Item $binPath/Microsoft.PowerShell.PSReadLine.dll $targetDir diff --git a/Polyfill/Polyfill.csproj b/Polyfill/Polyfill.csproj index 2cdccfbba..ea5103cac 100644 --- a/Polyfill/Polyfill.csproj +++ b/Polyfill/Polyfill.csproj @@ -3,7 +3,7 @@ Microsoft.PowerShell.PSReadLine.Polyfiller 1.0.0.0 - netstandard2.0;net6.0 + netstandard2.0;net8.0 true @@ -11,8 +11,8 @@ - - + + diff --git a/README.md b/README.md index d1ab3d11c..0b256ca35 100644 --- a/README.md +++ b/README.md @@ -160,7 +160,7 @@ The build script `build.ps1` can be used to bootstrap, build and test the projec * Build: `./build.ps1 -Configuration Debug` * Test: * Targeting .NET 4.7.2 (Windows only): `./build.ps1 -Test -Configuration Debug -Framework net472` - * Targeting .NET 6.0: `./build.ps1 -Test -Configuration Debug -Framework net6.0` + * Targeting .NET 6.0: `./build.ps1 -Test -Configuration Debug -Framework net8.0` After build, the produced artifacts can be found at `/bin/Debug`. diff --git a/appveyor.yml b/appveyor.yml deleted file mode 100644 index e989afe08..000000000 --- a/appveyor.yml +++ /dev/null @@ -1,26 +0,0 @@ - -image: Visual Studio 2022 - -environment: - POWERSHELL_TELEMETRY_OPTOUT: 1 - # Avoid expensive initialization of dotnet cli, see: http://donovanbrown.com/post/Stop-wasting-time-during-NET-Core-builds - DOTNET_SKIP_FIRST_TIME_EXPERIENCE: 1 - PSREADLINE_TESTRUN: 1 - -cache: - - '%HOMEDRIVE%%HOMEPATH%\.nuget\packages -> tools\helper.psm1' - -install: - - pwsh: | - Write-Host "PS Version: $($PSVersionTable.PSVersion)" - ./build.ps1 -Bootstrap - -build_script: - - pwsh: | - ./build.ps1 -Configuration Release - -test_script: - - pwsh: ./build.ps1 -Test -Configuration Release -Framework net472 - -artifacts: - - path: .\bin\Release\PSReadLine.zip diff --git a/build.ps1 b/build.ps1 index 481f2a271..fc462364c 100644 --- a/build.ps1 +++ b/build.ps1 @@ -16,7 +16,7 @@ Build the main module with the default configuration (Debug) targeting 'netstandard2.0'. .EXAMPLE PS > .\build.ps1 -Test - Run xUnit tests with the default configuration (Debug) and the default target framework (net472 on Windows or net6.0 otherwise). + Run xUnit tests with the default configuration (Debug) and the default target framework (net472 on Windows or net8.0 otherwise). .PARAMETER Clean Clean the local repo, but keep untracked files. .PARAMETER Bootstrap @@ -28,10 +28,10 @@ .PARAMETER Framework The target framework when testing: - net472: run tests with .NET Framework - - net6.0: run tests with .NET 6.0 + - net8.0: run tests with .NET 6.0 When not specified, the target framework is determined by the current OS platform: - use 'net472' on Windows - - use 'net6.0' on Unix platforms + - use 'net8.0' on Unix platforms #> [CmdletBinding(DefaultParameterSetName = 'default')] param( @@ -48,7 +48,7 @@ param( [switch] $CheckHelpContent, [Parameter(ParameterSetName = 'test')] - [ValidateSet("net472", "net6.0")] + [ValidateSet("net472", "net8.0")] [string] $Framework, [Parameter(ParameterSetName = 'default')] diff --git a/global.json b/global.json new file mode 100644 index 000000000..4141e1966 --- /dev/null +++ b/global.json @@ -0,0 +1,7 @@ +{ + "sdk": { + "version": "8.0.405", + "rollForward": "latestFeature", + "allowPrerelease": false + } +} diff --git a/nuget.config b/nuget.config index a10ce9b3d..f003b0fbd 100644 --- a/nuget.config +++ b/nuget.config @@ -2,9 +2,6 @@ - + - - - diff --git a/test/ConsoleFixture.cs b/test/ConsoleFixture.cs index 47544dc2a..d9ff59259 100644 --- a/test/ConsoleFixture.cs +++ b/test/ConsoleFixture.cs @@ -52,6 +52,15 @@ public static IEnumerable GetKeyboardLayoutList() public static string GetKeyboardLayout() { + // In CI environments like GitHub Actions, keyboard layout detection can fail + // or return incorrect results. Default to en-US in these cases. + if (Environment.GetEnvironmentVariable("GITHUB_ACTIONS") == "true" || + Environment.GetEnvironmentVariable("TF_BUILD") == "true" || + !RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) + { + return "en-US"; + } + var layout = GetKeyboardLayout(GetWindowThreadProcessId(GetForegroundWindow(), out var processId)); return GetLayoutNameFromHKL(layout); } @@ -100,4 +109,3 @@ public override string ToString() } } } - diff --git a/test/PSReadLine.Tests.csproj b/test/PSReadLine.Tests.csproj index 34598cbe9..70d0b9fe9 100644 --- a/test/PSReadLine.Tests.csproj +++ b/test/PSReadLine.Tests.csproj @@ -5,7 +5,7 @@ library UnitTestPSReadLine PSReadLine.Tests - net472;net6.0 + net472;net8.0 512 {3AC096D0-A1C2-E12C-1390-A8335801FDAB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} False @@ -19,8 +19,8 @@ - - + + diff --git a/tools/helper.psm1 b/tools/helper.psm1 index a3ee18a87..9ffddaebf 100644 --- a/tools/helper.psm1 +++ b/tools/helper.psm1 @@ -215,7 +215,7 @@ function Start-TestRun $testResultFile = Join-Path $testResultFolder $testResultFile $stdOutput, $stdError = @(New-TemporaryFile; New-TemporaryFile) - $arguments = 'test', '--no-build', '-c', $Configuration, '-f', $Framework, '--filter', $filter, '--logger', "xunit;LogFilePath=$testResultFile" + $arguments = 'test', '--no-build', '-c', $Configuration, '-f', $Framework, '--filter', $filter, '--logger', "xunit;LogFilePath=$testResultFile", '--logger', 'console;verbosity=normal' Start-Process -FilePath dotnet -Wait -RedirectStandardOutput $stdOutput -RedirectStandardError $stdError -ArgumentList $arguments Get-Content $stdOutput, $stdError @@ -224,15 +224,14 @@ function Start-TestRun try { - $env:PSREADLINE_TESTRUN = 1 Push-Location "$RepoRoot/test" $xUnitTestExecuted = $true if ($IsWindowsEnv) { - if ($env:APPVEYOR -or $env:TF_BUILD) + if ($env:GITHUB_ACTIONS -or $env:TF_BUILD) { - # AppVeyor CI builder only has en-US keyboard layout installed. + # GitHub Actions CI builder only has en-US keyboard layout installed. # We have to run tests from a new process because `GetCurrentKeyboardLayout` simply fails when called from # the `pwsh` process started by AppVeyor. Our xUnit tests depends on `GetCurrentKeyboardLayout` to tell if # a test case should run. @@ -298,7 +297,6 @@ function Start-TestRun finally { Pop-Location - Remove-Item env:PSREADLINE_TESTRUN } } diff --git a/tools/installPSResources.ps1 b/tools/installPSResources.ps1 new file mode 100644 index 000000000..05a1138f8 --- /dev/null +++ b/tools/installPSResources.ps1 @@ -0,0 +1,20 @@ +# Copyright (c) Microsoft Corporation. +# Licensed under the MIT License. +param( + [ValidateSet("PSGallery", "CFS")] + [string]$PSRepository = "PSGallery" +) + +if ($PSRepository -eq "CFS" -and -not (Get-PSResourceRepository -Name CFS -ErrorAction SilentlyContinue)) { + Register-PSResourceRepository -Name CFS -Uri "https://pkgs.dev.azure.com/powershell/PowerShell/_packaging/PowerShellGalleryMirror/nuget/v3/index.json" +} + +# NOTE: Due to a bug in Install-PSResource with upstream feeds, we have to +# request an exact version. Otherwise, if a newer version is available in the +# upstream feed, it will fail to install any version at all. +Install-PSResource -Verbose -TrustRepository -RequiredResource @{ + InvokeBuild = @{ + version = "5.12.1" + repository = $PSRepository + } +}