From cd841bd8906e762b800eec3b0c17a3902680e8e9 Mon Sep 17 00:00:00 2001 From: Shay Rojansky Date: Mon, 20 Apr 2026 18:58:53 +0200 Subject: [PATCH 1/2] CI: Consolidate GitHub Actions test workflows into unified Test.yaml Merge TestCosmos.yaml and TestSqlServer.yaml into a single Test.yaml workflow with dedicated jobs for Main, Cosmos, SqlServer, Sqlite, and Microsoft.Data.Sqlite. Additional fixes: - Use restore.cmd on Windows (restore.sh doesn't support MINGW/Git Bash) - Use portable shell commands for macOS compatibility - Conditionally exclude net481 TFM on non-Windows for Microsoft.Data.Sqlite tests - Disable assembly signing for F# test project on non-Windows (dotnet/fsharp#17451) - Fix ApiChief DecompilerFactory to resolve runtime assemblies on preview SDKs Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- .github/workflows/Test.yaml | 261 ++++++++++++++++++ .github/workflows/TestCosmos.yaml | 46 --- .github/workflows/TestSqlServer.yaml | 61 ---- EFCore.slnx | 3 +- .../ApiChief/Format/DecompilerFactory.cs | 13 +- .../EFCore.FSharp.FunctionalTests.fsproj | 2 + .../Microsoft.Data.Sqlite.Tests.csproj | 3 +- ...Microsoft.Data.Sqlite.sqlite3.Tests.csproj | 3 +- ...crosoft.Data.Sqlite.sqlite3mc.Tests.csproj | 3 +- 9 files changed, 281 insertions(+), 114 deletions(-) create mode 100644 .github/workflows/Test.yaml delete mode 100644 .github/workflows/TestCosmos.yaml delete mode 100644 .github/workflows/TestSqlServer.yaml diff --git a/.github/workflows/Test.yaml b/.github/workflows/Test.yaml new file mode 100644 index 00000000000..f729b1a9c46 --- /dev/null +++ b/.github/workflows/Test.yaml @@ -0,0 +1,261 @@ +name: Build + +on: + push: + branches: + - main + - feature/* + - release/* + pull_request: + branches: + - main + - feature/* + - release/* + +permissions: {} + +defaults: + run: + shell: bash + +env: + # Test projects requiring SQL Server (run in the sqlserver job, excluded from the main test job) + SQLSERVER_TEST_PROJECTS: >- + test/EFCore.SqlServer.FunctionalTests + test/EFCore.SqlServer.HierarchyId.Tests + test/EFCore.CrossStore.FunctionalTests + test/EFCore.OData.FunctionalTests + test/EFCore.AspNet.SqlServer.FunctionalTests + test/EFCore.VisualBasic.FunctionalTests + test/EFCore.FSharp.FunctionalTests + +jobs: + Main: + env: + # Additional projects to exclude (covered by other dedicated jobs, or not directly runnable) + ADDITIONAL_EXCLUDED_PROJECTS: >- + Cosmos.FunctionalTests + Specification.Tests + Microsoft.Data.Sqlite + EFCore.Sqlite + EFCore.AspNet.Sqlite + TrimmingTests + NativeAotTests + strategy: + fail-fast: false + matrix: + include: + - os: windows-2025 + - os: ubuntu-24.04 + - os: macos-15 + + runs-on: ${{ matrix.os }} + + steps: + - name: Checkout + uses: actions/checkout@v6 + + - name: Restore + if: runner.os != 'Windows' + run: ./restore.sh + + - name: Restore + if: runner.os == 'Windows' + shell: cmd + run: restore.cmd + + - name: Test + run: | + pattern=$(echo "$SQLSERVER_TEST_PROJECTS $ADDITIONAL_EXCLUDED_PROJECTS" | xargs -n1 | tr '\n' '|' | sed 's/|$//') + failed=0 + for proj in $(find test -maxdepth 2 \( -name '*.csproj' -o -name '*.fsproj' -o -name '*.vbproj' \) \ + | grep -v -E "$pattern"); do + echo "::group::Testing $proj" + dotnet test "$proj" || failed=1 + echo "::endgroup::" + done + exit $failed + + - name: Publish Test Results + uses: actions/upload-artifact@v7 + if: always() + with: + name: test-results-main-${{ matrix.os }} + path: artifacts/log/Debug/* + + Cosmos: + strategy: + fail-fast: false + matrix: + include: + - os: windows-2025 + - os: ubuntu-24.04 + + runs-on: ${{ matrix.os }} + + steps: + - name: Start Cosmos Emulator + if: runner.os == 'Windows' + shell: powershell + run: | + Import-Module "$env:ProgramFiles\Azure Cosmos DB Emulator\PSModules\Microsoft.Azure.CosmosDB.Emulator" + Start-CosmosDbEmulator -Timeout 540 -NoUI -NoTelemetry -NoFirewall -EnablePreview + + - name: Checkout + uses: actions/checkout@v6 + + - name: Restore + if: runner.os != 'Windows' + run: ./restore.sh + + - name: Restore + if: runner.os == 'Windows' + shell: cmd + run: restore.cmd + + - name: Test on Cosmos + run: dotnet test test/EFCore.Cosmos.FunctionalTests/EFCore.Cosmos.FunctionalTests.csproj + env: + Test__Cosmos__DefaultConnection: ${{ runner.os == 'Windows' && 'https://localhost:8081' || '' }} + Test__Cosmos__SkipConnectionCheck: ${{ runner.os == 'Windows' && 'true' || '' }} + + - name: Publish Test Results + uses: actions/upload-artifact@v7 + if: always() + with: + name: test-results-cosmos-${{ matrix.os }} + path: artifacts/log/Debug/* + + SqlServer: + runs-on: ubuntu-24.04 + + strategy: + fail-fast: false + matrix: + sqlserver_version: [2025, 2022, 2019] + + env: + MSSQL_SA_PASSWORD: 'PLACEHOLDERPass$$w0rd' + + services: + mssql: + image: mcr.microsoft.com/mssql/server:${{ matrix.sqlserver_version }}-latest + env: + ACCEPT_EULA: Y + SA_PASSWORD: ${{ env.MSSQL_SA_PASSWORD }} + ports: + - 1433:1433 + options: >- + --health-cmd="/opt/mssql-tools18/bin/sqlcmd -S localhost -U sa -P $SA_PASSWORD -Q 'SELECT 1' -C" + --health-start-period=20s + --health-interval=2s + --health-retries=30 + --health-timeout=5s + + steps: + - name: Checkout + uses: actions/checkout@v6 + + - name: Restore + run: ./restore.sh + + - name: Test on SQL Server + env: + Test__SqlServer__DefaultConnection: 'Server=localhost;Database=master;User=SA;Password=${{ env.MSSQL_SA_PASSWORD }};Connect Timeout=60;ConnectRetryCount=0;Trust Server Certificate=true' + run: | + failed=0 + for proj in $SQLSERVER_TEST_PROJECTS; do + echo "::group::Testing $proj" + dotnet test "$proj" || failed=1 + echo "::endgroup::" + done + exit $failed + + - name: Publish Test Results + uses: actions/upload-artifact@v7 + if: always() + with: + name: test-results-sqlserver-${{ matrix.sqlserver_version }} + path: artifacts/log/Debug/* + + Sqlite: + strategy: + fail-fast: false + matrix: + include: + - os: windows-2025 + - os: ubuntu-24.04 + + runs-on: ${{ matrix.os }} + + steps: + - name: Checkout + uses: actions/checkout@v6 + + - name: Restore + if: runner.os != 'Windows' + run: ./restore.sh + + - name: Restore + if: runner.os == 'Windows' + shell: cmd + run: restore.cmd + + - name: Test EF Core Sqlite + run: | + failed=0 + for proj in test/EFCore.Sqlite.FunctionalTests test/EFCore.Sqlite.Tests test/EFCore.AspNet.Sqlite.FunctionalTests; do + echo "::group::Testing $proj" + dotnet test "$proj" || failed=1 + echo "::endgroup::" + done + exit $failed + + - name: Publish Test Results + uses: actions/upload-artifact@v7 + if: always() + with: + name: test-results-sqlite-${{ matrix.os }} + path: artifacts/log/Debug/* + + microsoft-data-sqlite: + name: Microsoft.Data.Sqlite + strategy: + fail-fast: false + matrix: + include: + - os: windows-2025 + - os: ubuntu-24.04 + + runs-on: ${{ matrix.os }} + + steps: + - name: Checkout + uses: actions/checkout@v6 + + - name: Restore + if: runner.os != 'Windows' + run: ./restore.sh + + - name: Restore + if: runner.os == 'Windows' + shell: cmd + run: restore.cmd + + - name: Test Microsoft.Data.Sqlite + run: | + failed=0 + for proj in $(find test/Microsoft.Data.Sqlite.Tests -name '*.csproj' \ + | if [ "$RUNNER_OS" != "Windows" ]; then grep -v winsqlite3; else cat; fi); do + echo "::group::Testing $proj" + dotnet test "$proj" || failed=1 + echo "::endgroup::" + done + exit $failed + + - name: Publish Test Results + uses: actions/upload-artifact@v7 + if: always() + with: + name: test-results-microsoft-data-sqlite-${{ matrix.os }} + path: artifacts/log/Debug/* diff --git a/.github/workflows/TestCosmos.yaml b/.github/workflows/TestCosmos.yaml deleted file mode 100644 index 5f93e3e8990..00000000000 --- a/.github/workflows/TestCosmos.yaml +++ /dev/null @@ -1,46 +0,0 @@ -name: Test Cosmos - -on: - push: - branches: - - main - - feature/* - - release/* - pull_request: - branches: - - main - - feature/* - - release/* - -permissions: {} - -jobs: - build: - runs-on: windows-latest - - steps: - - name: Start Cosmos Emulator - run: | - Import-Module "$env:ProgramFiles\Azure Cosmos DB Emulator\PSModules\Microsoft.Azure.CosmosDB.Emulator" - Start-CosmosDbEmulator -Timeout 540 -NoUI -NoTelemetry -NoFirewall -EnablePreview - - - name: Checkout - uses: actions/checkout@v6 - - - name: Restore - run: restore.cmd - shell: cmd - - - name: Test on Cosmos - run: dotnet test test/EFCore.Cosmos.FunctionalTests/EFCore.Cosmos.FunctionalTests.csproj - shell: cmd - env: - Test__Cosmos__DefaultConnection: https://localhost:8081 - Test__Cosmos__SkipConnectionCheck: true - - - name: Publish Test Results - uses: actions/upload-artifact@v7 - if: always() - with: - name: test-results - path: artifacts/log/Debug/* diff --git a/.github/workflows/TestSqlServer.yaml b/.github/workflows/TestSqlServer.yaml deleted file mode 100644 index 8bc9aa1bab3..00000000000 --- a/.github/workflows/TestSqlServer.yaml +++ /dev/null @@ -1,61 +0,0 @@ -name: Test SQL Server - -on: - push: - branches: - - main - - feature/* - - release/* - pull_request: - branches: - - main - - feature/* - - release/* - -permissions: {} - -jobs: - test: - runs-on: ubuntu-24.04 - - strategy: - fail-fast: false - matrix: - sqlserver_version: [2025, 2022, 2019] - - env: - MSSQL_SA_PASSWORD: 'PLACEHOLDERPass$$w0rd' - - services: - mssql: - image: mcr.microsoft.com/mssql/server:${{ matrix.sqlserver_version }}-latest - env: - ACCEPT_EULA: Y - SA_PASSWORD: ${{ env.MSSQL_SA_PASSWORD }} - ports: - - 1433:1433 - options: >- - --health-cmd="/opt/mssql-tools18/bin/sqlcmd -S localhost -U sa -P $SA_PASSWORD -Q 'SELECT 1' -C" - --health-start-period=20s - --health-interval=2s - --health-retries=30 - --health-timeout=5s - - steps: - - name: Checkout - uses: actions/checkout@v6 - - - name: Restore - run: ./restore.sh - - - name: Test on SQL Server - env: - Test__SqlServer__DefaultConnection: 'Server=localhost;Database=master;User=SA;Password=${{ env.MSSQL_SA_PASSWORD }};Connect Timeout=60;ConnectRetryCount=0;Trust Server Certificate=true' - run: dotnet test test/EFCore.SqlServer.FunctionalTests - - - name: Publish Test Results - uses: actions/upload-artifact@v7 - if: always() - with: - name: test-results-sqlserver-${{ matrix.sqlserver_version }} - path: artifacts/log/Debug/* diff --git a/EFCore.slnx b/EFCore.slnx index 30a3b70e9da..bbd3b445bae 100644 --- a/EFCore.slnx +++ b/EFCore.slnx @@ -22,8 +22,7 @@ - - + diff --git a/eng/Tools/ApiChief/Format/DecompilerFactory.cs b/eng/Tools/ApiChief/Format/DecompilerFactory.cs index 5c61a49df9b..92c7c0cd884 100644 --- a/eng/Tools/ApiChief/Format/DecompilerFactory.cs +++ b/eng/Tools/ApiChief/Format/DecompilerFactory.cs @@ -1,8 +1,10 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. +using System.Runtime.InteropServices; using ICSharpCode.Decompiler; using ICSharpCode.Decompiler.CSharp; +using ICSharpCode.Decompiler.Metadata; namespace ApiChief.Format; @@ -32,7 +34,7 @@ internal static class DecompilerFactory CSharpFormattingOptions = Formatter.BaselineFormatting }; - public static CSharpDecompiler Create(string path) => new(path, _decompilerSettings); + public static CSharpDecompiler Create(string path) => new(path, CreateResolver(path), _decompilerSettings); public static CSharpDecompiler CreateWithXmlComments(string path) { @@ -41,6 +43,13 @@ public static CSharpDecompiler CreateWithXmlComments(string path) xmlCommentsSettings.CSharpFormattingOptions = Formatter.FormattingWithXmlComments; xmlCommentsSettings.ShowXmlDocumentation = true; - return new(path, xmlCommentsSettings); + return new(path, CreateResolver(path), xmlCommentsSettings); + } + + private static UniversalAssemblyResolver CreateResolver(string assemblyPath) + { + var resolver = new UniversalAssemblyResolver(assemblyPath, throwOnError: true, targetFramework: null); + resolver.AddSearchDirectory(RuntimeEnvironment.GetRuntimeDirectory()); + return resolver; } } diff --git a/test/EFCore.FSharp.FunctionalTests/EFCore.FSharp.FunctionalTests.fsproj b/test/EFCore.FSharp.FunctionalTests/EFCore.FSharp.FunctionalTests.fsproj index 6689e3bc456..39bc8921e5a 100644 --- a/test/EFCore.FSharp.FunctionalTests/EFCore.FSharp.FunctionalTests.fsproj +++ b/test/EFCore.FSharp.FunctionalTests/EFCore.FSharp.FunctionalTests.fsproj @@ -9,6 +9,8 @@ true + + false diff --git a/test/Microsoft.Data.Sqlite.Tests/Microsoft.Data.Sqlite.Tests.csproj b/test/Microsoft.Data.Sqlite.Tests/Microsoft.Data.Sqlite.Tests.csproj index 00507d8fa7b..9ffbf9421f2 100644 --- a/test/Microsoft.Data.Sqlite.Tests/Microsoft.Data.Sqlite.Tests.csproj +++ b/test/Microsoft.Data.Sqlite.Tests/Microsoft.Data.Sqlite.Tests.csproj @@ -1,7 +1,8 @@ - $(DefaultNetCoreTargetFramework);$(NetFrameworkCurrent) + $(DefaultNetCoreTargetFramework);$(NetFrameworkCurrent) + $(DefaultNetCoreTargetFramework) $(DefineConstants);E_SQLITE3 enable diff --git a/test/Microsoft.Data.Sqlite.Tests/Microsoft.Data.Sqlite.sqlite3.Tests.csproj b/test/Microsoft.Data.Sqlite.Tests/Microsoft.Data.Sqlite.sqlite3.Tests.csproj index b1ccc9dc6c5..f938e1f93e6 100644 --- a/test/Microsoft.Data.Sqlite.Tests/Microsoft.Data.Sqlite.sqlite3.Tests.csproj +++ b/test/Microsoft.Data.Sqlite.Tests/Microsoft.Data.Sqlite.sqlite3.Tests.csproj @@ -1,7 +1,8 @@ - $(DefaultNetCoreTargetFramework);$(NetFrameworkCurrent) + $(DefaultNetCoreTargetFramework);$(NetFrameworkCurrent) + $(DefaultNetCoreTargetFramework) $(DefineConstants);SQLITE3 enable diff --git a/test/Microsoft.Data.Sqlite.Tests/Microsoft.Data.Sqlite.sqlite3mc.Tests.csproj b/test/Microsoft.Data.Sqlite.Tests/Microsoft.Data.Sqlite.sqlite3mc.Tests.csproj index 49acbe62392..5fbf38e3d00 100644 --- a/test/Microsoft.Data.Sqlite.Tests/Microsoft.Data.Sqlite.sqlite3mc.Tests.csproj +++ b/test/Microsoft.Data.Sqlite.Tests/Microsoft.Data.Sqlite.sqlite3mc.Tests.csproj @@ -1,7 +1,8 @@ - $(DefaultNetCoreTargetFramework);$(NetFrameworkCurrent) + $(DefaultNetCoreTargetFramework);$(NetFrameworkCurrent) + $(DefaultNetCoreTargetFramework) $(DefineConstants);SQLITE3MC enable From 14761c910b0f886a24826819bbb3fa2e1c1b8e63 Mon Sep 17 00:00:00 2001 From: Shay Rojansky Date: Tue, 21 Apr 2026 09:26:51 +0200 Subject: [PATCH 2/2] Tweak triggerrs --- .github/workflows/{Test.yaml => Build.yml} | 14 -------------- 1 file changed, 14 deletions(-) rename .github/workflows/{Test.yaml => Build.yml} (94%) diff --git a/.github/workflows/Test.yaml b/.github/workflows/Build.yml similarity index 94% rename from .github/workflows/Test.yaml rename to .github/workflows/Build.yml index f729b1a9c46..3896d46ae10 100644 --- a/.github/workflows/Test.yaml +++ b/.github/workflows/Build.yml @@ -4,13 +4,7 @@ on: push: branches: - main - - feature/* - - release/* pull_request: - branches: - - main - - feature/* - - release/* permissions: {} @@ -70,9 +64,7 @@ jobs: failed=0 for proj in $(find test -maxdepth 2 \( -name '*.csproj' -o -name '*.fsproj' -o -name '*.vbproj' \) \ | grep -v -E "$pattern"); do - echo "::group::Testing $proj" dotnet test "$proj" || failed=1 - echo "::endgroup::" done exit $failed @@ -165,9 +157,7 @@ jobs: run: | failed=0 for proj in $SQLSERVER_TEST_PROJECTS; do - echo "::group::Testing $proj" dotnet test "$proj" || failed=1 - echo "::endgroup::" done exit $failed @@ -205,9 +195,7 @@ jobs: run: | failed=0 for proj in test/EFCore.Sqlite.FunctionalTests test/EFCore.Sqlite.Tests test/EFCore.AspNet.Sqlite.FunctionalTests; do - echo "::group::Testing $proj" dotnet test "$proj" || failed=1 - echo "::endgroup::" done exit $failed @@ -247,9 +235,7 @@ jobs: failed=0 for proj in $(find test/Microsoft.Data.Sqlite.Tests -name '*.csproj' \ | if [ "$RUNNER_OS" != "Windows" ]; then grep -v winsqlite3; else cat; fi); do - echo "::group::Testing $proj" dotnet test "$proj" || failed=1 - echo "::endgroup::" done exit $failed