Merge pull request #299 from ChrisJollyAU/net11-rc1 #147
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| name: Push | |
| on: | |
| push: | |
| branches: | |
| - '**' | |
| paths-ignore: | |
| - '**.md' | |
| release: | |
| types: | |
| - published | |
| env: | |
| DOTNET_SKIP_FIRST_TIME_EXPERIENCE: true | |
| DOTNET_CLI_TELEMETRY_OPTOUT: true | |
| DOTNET_NOLOGO: true | |
| PIPELINE_WORKSPACE: true | |
| DOTNET_CI: true | |
| checkoutFetchDepth: 1 | |
| buildConfiguration: 'Debug' | |
| skipTests: false | |
| deterministicTests: true | |
| uploadTestResults: true | |
| jobs: | |
| Preconditions: | |
| runs-on: ubuntu-latest | |
| outputs: | |
| lastCommitIsAutoCommit: ${{ steps.GetHeadCommitInfo.outputs.lastCommitIsAutoCommit }} | |
| lastCommitCreatedBeforeSeconds: ${{ steps.GetHeadCommitInfo.outputs.lastCommitCreatedBeforeSeconds }} | |
| steps: | |
| - name: 'General Information' | |
| shell: pwsh | |
| run: | | |
| echo 'EventName: ${{ github.event_name }}' | |
| - name: Checkout | |
| uses: actions/checkout@v5 | |
| with: | |
| fetch-depth: ${{ env.checkoutFetchDepth }} | |
| - name: 'Get Head Commit Info' | |
| id: GetHeadCommitInfo | |
| shell: pwsh | |
| run: | | |
| git log -${{ env.checkoutFetchDepth }} --pretty=%B | |
| $headCommitMessage = git log -1 --skip "$(${{ env.checkoutFetchDepth }} - 1)" --pretty=%B | |
| echo "headCommitMessage: = $headCommitMessage" | |
| $headCommitAuthorName = git log -1 --skip "$(${{ env.checkoutFetchDepth }} - 1)" --pretty=%an | |
| echo "headCommitAuthorName: = $headCommitAuthorName" | |
| $headCommitAuthorEmail = git log -1 --skip "$(${{ env.checkoutFetchDepth }} - 1)" --pretty=%ae | |
| echo "headCommitAuthorEmail: = $headCommitAuthorEmail" | |
| $headCommitDateTime = Get-Date (git log -1 --skip "$(${{ env.checkoutFetchDepth }} - 1)" --pretty=%ci) | |
| echo "headCommitDateTime: = $headCommitDateTime" | |
| $lastCommitIsAutoCommit = $headCommitAuthorEmail -eq 'github-actions@github.com' -and $headCommitMessage -eq '[GitHub Actions] Update green tests.' | |
| echo "lastCommitIsAutoCommit=$lastCommitIsAutoCommit" >> $env:GITHUB_OUTPUT | |
| echo "lastCommitIsAutoCommit: = $lastCommitIsAutoCommit" | |
| $lastCommitCreatedBeforeSeconds = [int]((Get-Date) - $headCommitDateTime).TotalSeconds | |
| echo "lastCommitCreatedBeforeSeconds=$lastCommitCreatedBeforeSeconds" >> $env:GITHUB_OUTPUT | |
| echo "lastCommitCreatedBeforeSeconds: = $lastCommitCreatedBeforeSeconds" | |
| Changes: | |
| runs-on: ubuntu-latest | |
| outputs: | |
| jet: ${{ steps.Decide.outputs.jet }} | |
| libred: ${{ steps.Decide.outputs.libred }} | |
| steps: | |
| - name: Checkout | |
| uses: actions/checkout@v5 | |
| with: | |
| fetch-depth: 0 | |
| - name: 'Filter Changed Paths' | |
| id: Filter | |
| uses: dorny/paths-filter@v4 | |
| with: | |
| # Diff only THIS push's commits. Without a base, paths-filter defaults a non-default-branch push to | |
| # the merge-base with the default branch (master), which on a long-lived branch like `libred` means | |
| # every push is compared against the whole ~869-file divergence — so every filter always matched. The | |
| # push's own delta (before..after) is what "did this push touch Jet/LibRed" actually means. On the | |
| # first push to a branch `before` is all-zeros; paths-filter treats that as "everything changed". | |
| base: ${{ github.event.before }} | |
| filters: | | |
| # Anything here rebuilds the world, so it belongs to both sides. | |
| shared: &shared | |
| - '.github/workflows/**' | |
| - 'Directory.Build.props' | |
| - 'Version.props' | |
| - 'global.json' | |
| - 'nuget.config' | |
| - 'NuGet.config' | |
| - 'Key.snk' | |
| - 'EFCore.Jet.sln' | |
| - 'src/Directory.Build.props' | |
| - 'test/Directory.Build.props' | |
| - 'test/Shared/**' | |
| jet: | |
| - *shared | |
| - 'src/Shared/**' | |
| - 'src/EFCore.Jet/**' | |
| - 'src/EFCore.Jet.Common/**' | |
| - 'src/EFCore.Jet.Data/**' | |
| - 'src/EFCore.Jet.Odbc/**' | |
| - 'src/EFCore.Jet.OleDb/**' | |
| - 'test/EFCore.Jet.Data.Tests/**' | |
| - 'test/EFCore.Jet.FunctionalTests/**' | |
| - 'test/EFCore.Jet.IntegrationTests/**' | |
| - 'test/EFCore.Jet.Tests/**' | |
| - 'test/JetProviderExceptionTests/**' | |
| libred: | |
| - *shared | |
| - 'src/LibRed/**' | |
| - 'test/LibRed.Ado.Tests/**' | |
| - 'test/LibRed.Core.Tests/**' | |
| - 'test/LibRed.Core.AccessTests/**' | |
| - 'test/LibRed.EFCore.Tests/**' | |
| - 'test/LibRed.Engine.Tests/**' | |
| - 'test/LibRed.Engine.AccessTests/**' | |
| - 'test/EFCore.LibRed.FunctionalTests/**' | |
| - 'test/EFCore.LibRed.Extended.FunctionalTests/**' | |
| - 'src/EFCore.Jet.Common/**' | |
| # Northwind.accdb lives here and every LibRed suite links to it as its fixture. | |
| - 'test/JetProviderExceptionTests/**' | |
| - name: 'Decide What To Run' | |
| id: Decide | |
| shell: pwsh | |
| run: | | |
| # A published release (or any event that isn't a push/PR) has no meaningful diff to filter | |
| # against, so it runs everything. | |
| $runEverything = '${{ github.event_name }}' -notin @('push', 'pull_request') | |
| $jet = $runEverything -or ('${{ steps.Filter.outputs.jet }}' -eq 'true') | |
| $libred = $runEverything -or ('${{ steps.Filter.outputs.libred }}' -eq 'true') | |
| echo "jet=$($jet.ToString().ToLowerInvariant())" >> $env:GITHUB_OUTPUT | |
| echo "libred=$($libred.ToString().ToLowerInvariant())" >> $env:GITHUB_OUTPUT | |
| echo "runEverything: $runEverything" | |
| echo "jet: $jet" | |
| echo "libred: $libred" | |
| BuildAndTest: | |
| needs: | |
| - Preconditions | |
| - Changes | |
| if: (needs.Preconditions.outputs.lastCommitIsAutoCommit != 'true' || needs.Preconditions.outputs.lastCommitCreatedBeforeSeconds > 300) && needs.Changes.outputs.jet == 'true' | |
| strategy: | |
| fail-fast: false | |
| matrix: | |
| aceVersion: | |
| - 2010 | |
| - 2016 | |
| aceArchitecture: | |
| - x64 | |
| - x86 | |
| dataAccessProviderType: | |
| - ODBC | |
| - OLE DB | |
| os: | |
| - windows-latest | |
| runs-on: ${{ matrix.os }} | |
| steps: | |
| - name: Checkout | |
| uses: actions/checkout@v5 | |
| # Defender scans every .accdb these suites write; see the action for the measurement. | |
| - name: Exclude test files from Defender | |
| uses: ./.github/actions/exclude-defender | |
| - name: Set additional variables | |
| shell: pwsh | |
| run: | | |
| $os = '${{ matrix.os }}'.Split('-')[0] | |
| echo "os=$os" >> $env:GITHUB_ENV | |
| $dotnetInstallDirectory = '.\.dotnet_${{ matrix.aceArchitecture }}' | |
| echo "dotnetInstallDirectory=$dotnetInstallDirectory" >> $env:GITHUB_ENV | |
| $dotnetExecutable = Join-Path $dotnetInstallDirectory 'dotnet.exe' | |
| echo "dotnetExecutable=$dotnetExecutable" >> $env:GITHUB_ENV | |
| $aceUrls = @{ | |
| '2010' = @{ | |
| 'x64' = 'https://cirrusredorg.github.io/EntityFrameworkCore.Jet/AccessDatabaseEngine_2010_x64.exe' | |
| 'x86' = 'https://cirrusredorg.github.io/EntityFrameworkCore.Jet/AccessDatabaseEngine_2010_x86.exe' | |
| 'silent' = '/passive /quiet /norestart REBOOT=ReallySuppress' | |
| } | |
| '2016' = @{ | |
| 'x64' = 'https://cirrusredorg.github.io/EntityFrameworkCore.Jet/AccessDatabaseEngine_2016_x64.exe' | |
| 'x86' = 'https://cirrusredorg.github.io/EntityFrameworkCore.Jet/AccessDatabaseEngine_2016_x86.exe' | |
| 'silent' = '/passive /quiet /norestart REBOOT=ReallySuppress' | |
| } | |
| } | |
| $aceUrl = $aceUrls['${{ matrix.aceVersion }}']['${{ matrix.aceArchitecture }}'] | |
| echo "aceUrl=$aceUrl" >> $env:GITHUB_ENV | |
| $aceSilentInstallArgument = $aceUrls['${{ matrix.aceVersion }}']['silent'] | |
| echo "aceSilentInstallArgument=$aceSilentInstallArgument" >> $env:GITHUB_ENV | |
| $defaultConnection = '${{ matrix.dataAccessProviderType }}' -eq 'ODBC' ? 'DBQ=Jet.accdb' : 'Data Source=Jet.accdb;Persist Security Info=False;' | |
| echo "defaultConnection=$defaultConnection" >> $env:GITHUB_ENV | |
| $matrixId = '${{ matrix.aceVersion }}-${{ matrix.aceArchitecture }}-' + '${{ matrix.dataAccessProviderType }}'.Replace(' ', '') + '${{ matrix.os }}' | |
| echo "matrixId=$matrixId" >> $env:GITHUB_ENV | |
| - name: Output Variables | |
| shell: pwsh | |
| run: | | |
| echo "os: ${{ env.os }}" | |
| echo "buildConfiguration: ${{ env.buildConfiguration }}" | |
| echo "aceVersion: ${{ matrix.aceVersion }}" | |
| echo "aceArchitecture: ${{ matrix.aceArchitecture }}" | |
| echo "aceUrl: ${{ env.aceUrl }}" | |
| echo "aceSilentInstallArgument: ${{ env.aceSilentInstallArgument }}" | |
| echo "dataAccessProviderType: ${{ matrix.dataAccessProviderType }}" | |
| echo "defaultConnection: ${{ env.defaultConnection }}" | |
| echo "matrixId: ${{ env.matrixId }}" | |
| echo "skipTests: ${{ env.skipTests }}" | |
| echo "dotnetInstallDirectory: ${{ env.dotnetInstallDirectory }}" | |
| echo "dotnetExecutable: ${{ env.dotnetExecutable }}" | |
| echo "github.event_name: ${{ github.event_name }}" | |
| echo "github.repository: ${{ github.repository }}" | |
| - name: .NET Information Before SDK Install | |
| shell: pwsh | |
| run: try { & '${{ env.dotnetExecutable }}' --info } catch { echo 'No ${{ matrix.aceArchitecture }} .NET SDK installed.' } | |
| - name: Install .NET SDK | |
| shell: pwsh | |
| run: | | |
| function Retry-Command { | |
| [CmdletBinding()] | |
| Param( | |
| [Parameter(Position=0, Mandatory=$true)] | |
| [ScriptBlock]$ScriptBlock, | |
| [Parameter(Position=1, Mandatory=$false)] | |
| [int]$Maximum = 5, | |
| [Parameter(Mandatory=$false)] | |
| [switch]$ExponentialBackoff | |
| ) | |
| $attempt = 0 | |
| do { | |
| if ($attempt -gt 0 -and $ExponentialBackoff) { | |
| Start-Sleep -Seconds ([Math]::Pow(2, $attempt) - 1) | |
| } | |
| $attempt++ | |
| try { | |
| $ScriptBlock.Invoke() | |
| return | |
| } catch { | |
| Write-Error $_.Exception.InnerException.Message -ErrorAction Continue | |
| } | |
| } while ($attempt -lt $Maximum) | |
| throw 'Max retries exceeded.' | |
| } | |
| Retry-Command { | |
| &([ScriptBlock]::Create((Invoke-WebRequest -UseBasicParsing 'https://dot.net/v1/dotnet-install.ps1'))) -JSonFile global.json -Architecture '${{ matrix.aceArchitecture }}' -InstallDir '${{ env.dotnetInstallDirectory }}' -Verbose | |
| } -Maximum 10 -ExponentialBackoff | |
| # x86 hosts the tests in a 2GB user address space, and ACE is the one native component in that | |
| # process. On ACE 2010 the same driver and tests get through all 23,509 of shard 3 on x64 and die | |
| # partway on x86, which is the shape of address-space pressure - so lift the ceiling to 4GB by | |
| # setting IMAGE_FILE_LARGE_ADDRESS_AWARE (COFF Characteristics 0x0020). Patched directly rather | |
| # than via editbin so no vcvars environment is needed; signatures are invalidated, which does not | |
| # matter on an ephemeral runner. (ACE 2016 dies early on BOTH architectures, so this cannot help | |
| # there - its failure is the driver, not address space.) | |
| # | |
| # This runs BEFORE the build: MSBuild keeps worker nodes alive after a build and they hold | |
| # dotnet.exe open, so patching it afterwards fails with "being used by another process". | |
| - name: 'Make the x86 SDK large-address-aware' | |
| if: matrix.aceArchitecture == 'x86' | |
| shell: pwsh | |
| run: | | |
| function Set-LargeAddressAware { | |
| param([string]$Path) | |
| $bytes = [System.IO.File]::ReadAllBytes($Path) | |
| $peOffset = [BitConverter]::ToInt32($bytes, 0x3C) | |
| if ([BitConverter]::ToUInt32($bytes, $peOffset) -ne 0x00004550) { return 'not-a-pe' } | |
| $machine = [BitConverter]::ToUInt16($bytes, $peOffset + 4) | |
| if ($machine -ne 0x014C) { return "skipped-$('0x{0:X4}' -f $machine)" } | |
| $charOffset = $peOffset + 22 | |
| $characteristics = [BitConverter]::ToUInt16($bytes, $charOffset) | |
| if (($characteristics -band 0x0020) -ne 0) { return 'already' } | |
| [BitConverter]::GetBytes([UInt16]($characteristics -bor 0x0020)).CopyTo($bytes, $charOffset) | |
| [System.IO.File]::WriteAllBytes($Path, $bytes) | |
| $verify = [System.IO.File]::ReadAllBytes($Path) | |
| if (([BitConverter]::ToUInt16($verify, $charOffset) -band 0x0020) -eq 0) { return 'FAILED' } | |
| return 'patched' | |
| } | |
| $target = '${{ env.dotnetExecutable }}' | |
| if (Test-Path $target) { | |
| echo ("{0,-9} {1}" -f (Set-LargeAddressAware -Path $target), $target) | |
| } else { | |
| echo "missing: $target" | |
| } | |
| - name: .NET Information After SDK Install | |
| shell: pwsh | |
| run: try { & '${{ env.dotnetExecutable }}' --info } catch { echo 'No ${{ matrix.aceArchitecture }} .NET SDK installed.' } | |
| - name: ACE Information Before ACE Install | |
| shell: pwsh | |
| run: | | |
| 'DAO:' | |
| Get-ChildItem 'HKLM:\SOFTWARE\Classes\DAO.DBEngine*' | Select-Object | |
| 'OLE DB:' | |
| foreach ($provider in [System.Data.OleDb.OleDbEnumerator]::GetRootEnumerator()) | |
| { | |
| $v = New-Object PSObject | |
| for ($i = 0; $i -lt $provider.FieldCount; $i++) | |
| { | |
| Add-Member -in $v NoteProperty $provider.GetName($i) $provider.GetValue($i) | |
| } | |
| $v | |
| } | |
| - name: Install Access Database Engine | |
| shell: pwsh | |
| run: | | |
| $setupFileName = 'AccessDatabaseEngine_${{ matrix.aceVersion }}_${{ matrix.aceArchitecture }}.exe' | |
| Invoke-WebRequest '${{ env.aceUrl }}' -OutFile $setupFileName | |
| & ".\$setupFileName" ${{ env.aceSilentInstallArgument }} | Out-Default | |
| - name: ACE Information After ACE Install | |
| shell: pwsh | |
| run: | | |
| 'DAO:' | |
| Get-ChildItem 'HKLM:\SOFTWARE\Classes\DAO.DBEngine*' | Select-Object | |
| 'OLE DB:' | |
| foreach ($provider in [System.Data.OleDb.OleDbEnumerator]::GetRootEnumerator()) | |
| { | |
| $v = New-Object PSObject | |
| for ($i = 0; $i -lt $provider.FieldCount; $i++) | |
| { | |
| Add-Member -in $v NoteProperty $provider.GetName($i) $provider.GetValue($i) | |
| } | |
| $v | |
| } | |
| - name: Build Solution | |
| shell: pwsh | |
| run: | | |
| & '${{ env.dotnetExecutable }}' build --configuration '${{ env.buildConfiguration }}' | |
| # The apphosts the build emits are the other candidate for the process that ends up holding ACE, | |
| # depending on whether VSTest launches the output-directory apphost or 'dotnet exec testhost.dll'. | |
| # Shut the build server down first so nothing is still holding these open. | |
| - name: 'Make the x86 test hosts large-address-aware' | |
| if: matrix.aceArchitecture == 'x86' | |
| shell: pwsh | |
| run: | | |
| function Set-LargeAddressAware { | |
| param([string]$Path) | |
| $bytes = [System.IO.File]::ReadAllBytes($Path) | |
| $peOffset = [BitConverter]::ToInt32($bytes, 0x3C) | |
| if ([BitConverter]::ToUInt32($bytes, $peOffset) -ne 0x00004550) { return 'not-a-pe' } | |
| $machine = [BitConverter]::ToUInt16($bytes, $peOffset + 4) | |
| if ($machine -ne 0x014C) { return "skipped-$('0x{0:X4}' -f $machine)" } | |
| $charOffset = $peOffset + 22 | |
| $characteristics = [BitConverter]::ToUInt16($bytes, $charOffset) | |
| if (($characteristics -band 0x0020) -ne 0) { return 'already' } | |
| [BitConverter]::GetBytes([UInt16]($characteristics -bor 0x0020)).CopyTo($bytes, $charOffset) | |
| [System.IO.File]::WriteAllBytes($Path, $bytes) | |
| $verify = [System.IO.File]::ReadAllBytes($Path) | |
| if (([BitConverter]::ToUInt16($verify, $charOffset) -band 0x0020) -eq 0) { return 'FAILED' } | |
| return 'patched' | |
| } | |
| & '${{ env.dotnetExecutable }}' build-server shutdown | Out-Null | |
| $results = @{} | |
| foreach ($target in (Get-ChildItem -Path '. est' -Recurse -Filter '*.exe' -ErrorAction SilentlyContinue | | |
| Where-Object { $_.FullName -match '\bin\' } | ForEach-Object { $_.FullName })) { | |
| $state = Set-LargeAddressAware -Path $target | |
| $results[$state] = 1 + ($results[$state] ?? 0) | |
| if ($state -in 'patched', 'already', 'FAILED') { | |
| echo ("{0,-9} {1}" -f $state, (Resolve-Path $target -Relative)) | |
| } | |
| } | |
| echo '' | |
| echo (($results.GetEnumerator() | Sort-Object Name | ForEach-Object { "$($_.Key)=$($_.Value)" }) -join ' ') | |
| if ($results['FAILED']) { echo 'Could not set the flag on one or more binaries.'; exit 1 } | |
| - name: 'Run Tests: EFCore.Jet.Data.Tests' | |
| if: always() && env.skipTests != 'true' | |
| shell: pwsh | |
| run: | | |
| $env:EFCoreJet_DefaultConnection = '${{ env.defaultConnection }}' | |
| # No --verbosity detailed: it dumps every test's captured output (EF logs the compiled shaper | |
| # expression tree per query under the Query category), which ran to ~62,000 lines in 43s per shard | |
| # and got truncated by GitHub anyway. Nothing consumes it - the green-tests extraction parses the | |
| # trx, and crash detection looks for Sequence_* blame dumps - so it cost console I/O for a log too | |
| # big to read. On these sequential suites those writes sit directly on the critical path. | |
| & '${{ env.dotnetExecutable }}' test .\test\EFCore.Jet.Data.Tests --configuration '${{ env.buildConfiguration }}' -p:FixedTestOrder=${{ env.deterministicTests }} --logger trx --blame-hang-timeout 3m | |
| # EFCore.Jet.Tests is not run: the project compiles to an assembly with no tests in it. Its only two | |
| # test files have been <Compile Remove>d since 45bae420 (the initial EF 9 update, July 2024), so the | |
| # step spent two years reporting green over an empty run. Much of what is in those files appears to | |
| # be covered by EFCore.Jet.FunctionalTests now; restore the step if they come back into the build. | |
| - name: 'Run Tests: EFCore.Jet.FunctionalTests (Shard 1 - Query Core)' | |
| if: always() && env.skipTests != 'true' | |
| shell: pwsh | |
| run: | | |
| $shardDir = '.\test\EFCore.Jet.FunctionalTests\TestResults\shard1' | |
| for ($i = 0; $i -lt 3; $i++) { | |
| if (Test-Path $shardDir -PathType Container) { | |
| Get-ChildItem $shardDir | Remove-Item -Recurse -Force | |
| } | |
| $env:EFCoreJet_DefaultConnection = '${{ env.defaultConnection }}' | |
| & '${{ env.dotnetExecutable }}' test .\test\EFCore.Jet.FunctionalTests --configuration '${{ env.buildConfiguration }}' -p:FixedTestOrder=${{ env.deterministicTests }} --logger trx --blame-hang-timeout 3m --results-directory $shardDir --filter "FullyQualifiedName~.FunctionalTests.Query.&FullyQualifiedName!~Northwind&FullyQualifiedName!~GearsOfWar" | |
| # | |
| # Check for test runner crashes: | |
| # | |
| $currentTestRunTrx = Get-ChildItem $shardDir -Filter '*.trx' | Sort-Object LastWriteTime | Select-Object -Last 1 | |
| if ($null -eq $currentTestRunTrx) { | |
| echo 'Test runner log file is missing.' | |
| exit 3 | |
| } | |
| $currentTestRunDir = Join-Path $shardDir $currentTestRunTrx.BaseName | |
| if (Test-Path $currentTestRunDir) { | |
| if ($null -ne (Get-ChildItem $currentTestRunDir -Filter 'Sequence_*' -Recurse)) { | |
| # Split string because searching the log for that phrase should only show actual crashes and not this line. | |
| echo ('Test runner cras' + 'hed.') | |
| continue | |
| } | |
| } | |
| echo 'Test runner ran until the end.' | |
| break | |
| } | |
| $establishedGreenTestsFilePath = ".\test\EFCore.Jet.FunctionalTests\GreenTests\ace_${{ matrix.aceVersion }}_$('${{ matrix.dataAccessProviderType }}'.Replace(' ', '').ToLowerInvariant())_${{ matrix.aceArchitecture }}.txt" | |
| $failIfKeepsCrashing = Test-Path $establishedGreenTestsFilePath | |
| if ($i -ge 3 -and $failIfKeepsCrashing) { | |
| echo 'Test runner keeps crashing.' | |
| exit 2 | |
| } | |
| exit 0 | |
| - name: 'Run Tests: EFCore.Jet.FunctionalTests (Shard 2 - Query Associations and Translations)' | |
| if: always() && env.skipTests != 'true' | |
| shell: pwsh | |
| run: | | |
| $shardDir = '.\test\EFCore.Jet.FunctionalTests\TestResults\shard2' | |
| for ($i = 0; $i -lt 3; $i++) { | |
| if (Test-Path $shardDir -PathType Container) { | |
| Get-ChildItem $shardDir | Remove-Item -Recurse -Force | |
| } | |
| $env:EFCoreJet_DefaultConnection = '${{ env.defaultConnection }}' | |
| & '${{ env.dotnetExecutable }}' test .\test\EFCore.Jet.FunctionalTests --configuration '${{ env.buildConfiguration }}' -p:FixedTestOrder=${{ env.deterministicTests }} --logger trx --blame-hang-timeout 3m --results-directory $shardDir --filter "FullyQualifiedName~.FunctionalTests.Query.Northwind|FullyQualifiedName~GearsOfWar" | |
| # | |
| # Check for test runner crashes: | |
| # | |
| $currentTestRunTrx = Get-ChildItem $shardDir -Filter '*.trx' | Sort-Object LastWriteTime | Select-Object -Last 1 | |
| if ($null -eq $currentTestRunTrx) { | |
| echo 'Test runner log file is missing.' | |
| exit 3 | |
| } | |
| $currentTestRunDir = Join-Path $shardDir $currentTestRunTrx.BaseName | |
| if (Test-Path $currentTestRunDir) { | |
| if ($null -ne (Get-ChildItem $currentTestRunDir -Filter 'Sequence_*' -Recurse)) { | |
| # Split string because searching the log for that phrase should only show actual crashes and not this line. | |
| echo ('Test runner cras' + 'hed.') | |
| continue | |
| } | |
| } | |
| echo 'Test runner ran until the end.' | |
| break | |
| } | |
| $establishedGreenTestsFilePath = ".\test\EFCore.Jet.FunctionalTests\GreenTests\ace_${{ matrix.aceVersion }}_$('${{ matrix.dataAccessProviderType }}'.Replace(' ', '').ToLowerInvariant())_${{ matrix.aceArchitecture }}.txt" | |
| $failIfKeepsCrashing = Test-Path $establishedGreenTestsFilePath | |
| if ($i -ge 3 -and $failIfKeepsCrashing) { | |
| echo 'Test runner keeps crashing.' | |
| exit 2 | |
| } | |
| exit 0 | |
| - name: 'Run Tests: EFCore.Jet.FunctionalTests (Shard 3 - Non-Query, excluding CompiledModel)' | |
| if: always() && env.skipTests != 'true' | |
| shell: pwsh | |
| run: | | |
| $shardDir = '.\test\EFCore.Jet.FunctionalTests\TestResults\shard3' | |
| for ($i = 0; $i -lt 3; $i++) { | |
| if (Test-Path $shardDir -PathType Container) { | |
| Get-ChildItem $shardDir | Remove-Item -Recurse -Force | |
| } | |
| $env:EFCoreJet_DefaultConnection = '${{ env.defaultConnection }}' | |
| & '${{ env.dotnetExecutable }}' test .\test\EFCore.Jet.FunctionalTests --configuration '${{ env.buildConfiguration }}' -p:FixedTestOrder=${{ env.deterministicTests }} --logger trx --blame-hang-timeout 3m --results-directory $shardDir --filter "FullyQualifiedName!~.FunctionalTests.Query.&FullyQualifiedName!~CompiledModel" | |
| # | |
| # Check for test runner crashes: | |
| # | |
| $currentTestRunTrx = Get-ChildItem $shardDir -Filter '*.trx' | Sort-Object LastWriteTime | Select-Object -Last 1 | |
| if ($null -eq $currentTestRunTrx) { | |
| echo 'Test runner log file is missing.' | |
| exit 3 | |
| } | |
| $currentTestRunDir = Join-Path $shardDir $currentTestRunTrx.BaseName | |
| if (Test-Path $currentTestRunDir) { | |
| if ($null -ne (Get-ChildItem $currentTestRunDir -Filter 'Sequence_*' -Recurse)) { | |
| # Split string because searching the log for that phrase should only show actual crashes and not this line. | |
| echo ('Test runner cras' + 'hed.') | |
| continue | |
| } | |
| } | |
| echo 'Test runner ran until the end.' | |
| break | |
| } | |
| $establishedGreenTestsFilePath = ".\test\EFCore.Jet.FunctionalTests\GreenTests\ace_${{ matrix.aceVersion }}_$('${{ matrix.dataAccessProviderType }}'.Replace(' ', '').ToLowerInvariant())_${{ matrix.aceArchitecture }}.txt" | |
| $failIfKeepsCrashing = Test-Path $establishedGreenTestsFilePath | |
| if ($i -ge 3 -and $failIfKeepsCrashing) { | |
| echo 'Test runner keeps crashing.' | |
| exit 2 | |
| } | |
| exit 0 | |
| - name: 'Run Tests: EFCore.Jet.FunctionalTests (Shard 4 - CompiledModel)' | |
| if: always() && env.skipTests != 'true' | |
| shell: pwsh | |
| run: | | |
| $shardDir = '.\test\EFCore.Jet.FunctionalTests\TestResults\shard4' | |
| for ($i = 0; $i -lt 3; $i++) { | |
| if (Test-Path $shardDir -PathType Container) { | |
| Get-ChildItem $shardDir | Remove-Item -Recurse -Force | |
| } | |
| $env:EFCoreJet_DefaultConnection = '${{ env.defaultConnection }}' | |
| & '${{ env.dotnetExecutable }}' test .\test\EFCore.Jet.FunctionalTests --configuration '${{ env.buildConfiguration }}' -p:FixedTestOrder=${{ env.deterministicTests }} --logger trx --blame-hang-timeout 3m --results-directory $shardDir --filter "FullyQualifiedName~CompiledModel" | |
| # | |
| # Check for test runner crashes: | |
| # | |
| $currentTestRunTrx = Get-ChildItem $shardDir -Filter '*.trx' | Sort-Object LastWriteTime | Select-Object -Last 1 | |
| if ($null -eq $currentTestRunTrx) { | |
| echo 'Test runner log file is missing.' | |
| exit 3 | |
| } | |
| $currentTestRunDir = Join-Path $shardDir $currentTestRunTrx.BaseName | |
| if (Test-Path $currentTestRunDir) { | |
| if ($null -ne (Get-ChildItem $currentTestRunDir -Filter 'Sequence_*' -Recurse)) { | |
| # Split string because searching the log for that phrase should only show actual crashes and not this line. | |
| echo ('Test runner cras' + 'hed.') | |
| continue | |
| } | |
| } | |
| echo 'Test runner ran until the end.' | |
| break | |
| } | |
| $establishedGreenTestsFilePath = ".\test\EFCore.Jet.FunctionalTests\GreenTests\ace_${{ matrix.aceVersion }}_$('${{ matrix.dataAccessProviderType }}'.Replace(' ', '').ToLowerInvariant())_${{ matrix.aceArchitecture }}.txt" | |
| $failIfKeepsCrashing = Test-Path $establishedGreenTestsFilePath | |
| if ($i -ge 3 -and $failIfKeepsCrashing) { | |
| echo 'Test runner keeps crashing.' | |
| exit 2 | |
| } | |
| exit 0 | |
| - name: 'Rename Test Results' | |
| if: always() && env.skipTests != 'true' | |
| shell: pwsh | |
| run: | | |
| Get-ChildItem -Filter '*.trx' -Recurse | Sort-Object LastWriteTime | ForEach { Rename-Item $_.FullName "ace_${{ matrix.aceVersion }}_$('${{ matrix.dataAccessProviderType }}'.Replace(' ', '').ToLowerInvariant())_${{ matrix.aceArchitecture }}_$($_.Name)" -Verbose } | |
| - name: 'Upload Test Results' | |
| if: always() && env.skipTests != 'true' && env.uploadTestResults == 'true' | |
| uses: actions/upload-artifact@v6 | |
| with: | |
| name: test-results_${{ env.matrixId }} | |
| path: | | |
| test\EFCore.Jet.Data.Tests\TestResults\*.trx | |
| test\EFCore.Jet.FunctionalTests\TestResults\**\*.trx | |
| - name: 'Check Tests: EFCore.Jet.FunctionalTests' | |
| if: env.skipTests != 'true' | |
| shell: pwsh | |
| run: | | |
| # Collect and merge test results from all shards. | |
| $testResultsDir = '.\test\EFCore.Jet.FunctionalTests\TestResults' | |
| $allTrxFiles = @(Get-ChildItem $testResultsDir -Filter '*.trx' -Recurse) | |
| if ($allTrxFiles.Count -eq 0) { | |
| echo 'No test result files found.' | |
| exit 3 | |
| } | |
| $allNodes = @() | |
| foreach ($trxFile in $allTrxFiles) { | |
| $allNodes += (Select-Xml -Path $trxFile.FullName -XPath "//ns:UnitTestResult" -Namespace @{"ns"="http://microsoft.com/schemas/VisualStudio/TeamTest/2010"}).Node | |
| } | |
| $allTestsFilePath = Join-Path $testResultsDir 'combined_All.txt' | |
| $allNodes | Sort-Object -Property testName -CaseSensitive | ForEach-Object { "$($_.outcome -eq 'Passed' ? 'P' : $_.outcome -eq 'NotExecuted' ? 'N' : $_.outcome -eq 'Failed' ? 'F' : 'U') $($_.testName)" } | Set-Content $allTestsFilePath | |
| $greenTestsFilePath = Join-Path $testResultsDir 'combined_Passed.txt' | |
| Get-Content $allTestsFilePath | Where-Object { $_.StartsWith('P ') } | ForEach-Object { $_.Substring(2) } | Set-Content $greenTestsFilePath | |
| # Compare test file against previously committed file. | |
| $establishedGreenTestsFilePath = ".\test\EFCore.Jet.FunctionalTests\GreenTests\ace_${{ matrix.aceVersion }}_$('${{ matrix.dataAccessProviderType }}'.Replace(' ', '').ToLowerInvariant())_${{ matrix.aceArchitecture }}.txt" | |
| if (Test-Path $establishedGreenTestsFilePath) { | |
| $diffResult = Compare-Object (Get-Content $establishedGreenTestsFilePath) (Get-Content $greenTestsFilePath) | |
| $notGreenAnymore = $diffResult | Where-Object { $_.SideIndicator -eq '<=' } | Select-Object -ExpandProperty InputObject | |
| if ($null -ne $notGreenAnymore) { | |
| echo "`nThe following $(@($notGreenAnymore).Length) tests passed in previous runs, but didn't pass in this run:`n" | |
| $notGreenAnymore | |
| exit 1 | |
| } | |
| echo 'All tests that passed in previous runs still passed in this run.' | |
| $newlyGreenTests = $diffResult | Where-Object { $_.SideIndicator -eq '=>' } | Select-Object -ExpandProperty InputObject | |
| if ($newlyGreenTests.Length -gt 0) { | |
| Copy-Item $greenTestsFilePath $establishedGreenTestsFilePath -Force -Verbose | |
| echo "`nThe following new tests passed that did not pass before:`n" | |
| $newlyGreenTests | |
| $commitGreenTestsFile = $establishedGreenTestsFilePath | |
| echo "commitGreenTestsFile=$commitGreenTestsFile" >> $env:GITHUB_ENV | |
| } | |
| } | |
| echo 'Check succeeded.' | |
| - name: 'Upload Green Tests' | |
| if: ${{ env.commitGreenTestsFile != '' }} | |
| uses: actions/upload-artifact@v6 | |
| with: | |
| name: green-tests_${{ env.matrixId }} | |
| path: ${{ env.commitGreenTestsFile }} | |
| LibRed: | |
| needs: | |
| - Preconditions | |
| - Changes | |
| if: (needs.Preconditions.outputs.lastCommitIsAutoCommit != 'true' || needs.Preconditions.outputs.lastCommitCreatedBeforeSeconds > 300) && needs.Changes.outputs.libred == 'true' | |
| strategy: | |
| fail-fast: false | |
| matrix: | |
| os: | |
| - ubuntu-latest | |
| - windows-latest | |
| - macos-latest | |
| # ARM64 legs. LibRed is fully managed with no ACE dependency, so these are the ones that | |
| # actually prove the cross-platform claim on a non-x64 architecture. Excludes LibRedAccess, | |
| # which cross-checks against the real Access engine and so needs Windows x64 with ACE. | |
| - ubuntu-24.04-arm | |
| - windows-11-arm | |
| runs-on: ${{ matrix.os }} | |
| steps: | |
| - name: Checkout | |
| uses: actions/checkout@v5 | |
| # Defender scans every .accdb these suites write; see the action for the measurement. | |
| - name: Exclude test files from Defender | |
| uses: ./.github/actions/exclude-defender | |
| - name: Install .NET SDK | |
| uses: actions/setup-dotnet@v5 | |
| with: | |
| global-json-file: global.json | |
| - name: .NET Information | |
| run: dotnet --info | |
| - name: 'Run Tests: LibRed.Engine.Tests' | |
| if: env.skipTests != 'true' | |
| run: dotnet test ./test/LibRed.Engine.Tests --configuration ${{ env.buildConfiguration }} -p:FixedTestOrder=${{ env.deterministicTests }} --blame-hang-timeout 3m | |
| # The file-format half of LibRed.Core.Tests. It reads and writes .accdb files with LibRed alone — the | |
| # cross-checks against the real Access engine live in LibRed.Core.AccessTests — so it belongs on this | |
| # matrix rather than the Windows one, and reading the on-disk format on Linux/macOS/ARM64 is the part | |
| # of the cross-platform claim that was previously only asserted for the engine. | |
| - name: 'Run Tests: LibRed.Core.Tests' | |
| if: always() && env.skipTests != 'true' | |
| run: dotnet test ./test/LibRed.Core.Tests --configuration ${{ env.buildConfiguration }} -p:FixedTestOrder=${{ env.deterministicTests }} --blame-hang-timeout 3m | |
| # The rest of the LibRed suites cross-check LibRed's output against the real engine over OLE DB, | |
| # so unlike the job above they do need Windows with ACE installed. | |
| LibRedAccess: | |
| needs: | |
| - Preconditions | |
| - Changes | |
| if: (needs.Preconditions.outputs.lastCommitIsAutoCommit != 'true' || needs.Preconditions.outputs.lastCommitCreatedBeforeSeconds > 300) && needs.Changes.outputs.libred == 'true' | |
| strategy: | |
| fail-fast: false | |
| matrix: | |
| aceVersion: | |
| - 2016 | |
| runs-on: windows-latest | |
| steps: | |
| - name: Checkout | |
| uses: actions/checkout@v5 | |
| # Defender scans every .accdb these suites write; see the action for the measurement. | |
| - name: Exclude test files from Defender | |
| uses: ./.github/actions/exclude-defender | |
| - name: Install .NET SDK | |
| uses: actions/setup-dotnet@v5 | |
| with: | |
| global-json-file: global.json | |
| - name: Install Access Database Engine | |
| shell: pwsh | |
| run: | | |
| $setupFileName = 'AccessDatabaseEngine_${{ matrix.aceVersion }}_x64.exe' | |
| Invoke-WebRequest "https://cirrusredorg.github.io/EntityFrameworkCore.Jet/$setupFileName" -OutFile $setupFileName | |
| & ".\$setupFileName" /passive /quiet /norestart REBOOT=ReallySuppress | Out-Default | |
| - name: 'ACE Information' | |
| shell: pwsh | |
| run: | | |
| foreach ($provider in [System.Data.OleDb.OleDbEnumerator]::GetRootEnumerator()) | |
| { | |
| $v = New-Object PSObject | |
| for ($i = 0; $i -lt $provider.FieldCount; $i++) | |
| { | |
| Add-Member -in $v NoteProperty $provider.GetName($i) $provider.GetValue($i) | |
| } | |
| $v | |
| } | |
| # The file-format tests that cross-check against ACE. Their ACE-free half runs on the five-platform | |
| # LibRed job above. | |
| - name: 'Run Tests: LibRed.Core.AccessTests' | |
| if: env.skipTests != 'true' | |
| shell: pwsh | |
| run: dotnet test .\test\LibRed.Core.AccessTests --configuration '${{ env.buildConfiguration }}' -p:FixedTestOrder=${{ env.deterministicTests }} --blame-hang-timeout 5m | |
| # The engine tests that cross-check against ACE. They belong here rather than in the cross-platform | |
| # LibRed job above, which runs on five platforms precisely to prove LibRed needs no ACE at all. | |
| - name: 'Run Tests: LibRed.Engine.AccessTests' | |
| if: always() && env.skipTests != 'true' | |
| shell: pwsh | |
| run: dotnet test .\test\LibRed.Engine.AccessTests --configuration '${{ env.buildConfiguration }}' -p:FixedTestOrder=${{ env.deterministicTests }} --blame-hang-timeout 5m | |
| - name: 'Run Tests: LibRed.Ado.Tests' | |
| if: always() && env.skipTests != 'true' | |
| shell: pwsh | |
| run: dotnet test .\test\LibRed.Ado.Tests --configuration '${{ env.buildConfiguration }}' -p:FixedTestOrder=${{ env.deterministicTests }} --blame-hang-timeout 5m | |
| - name: 'Run Tests: LibRed.EFCore.Tests' | |
| if: always() && env.skipTests != 'true' | |
| shell: pwsh | |
| run: dotnet test .\test\LibRed.EFCore.Tests --configuration '${{ env.buildConfiguration }}' -p:FixedTestOrder=${{ env.deterministicTests }} --blame-hang-timeout 5m | |
| LibRedFunctional: | |
| needs: | |
| - Preconditions | |
| - Changes | |
| # Non-blocking for now: both suites still fail in the low hundreds out of ~38,000 run, so the job would | |
| # be red on every push and quickly learn to be ignored. It still runs on every push and the log is there | |
| # to read. Drop this line once the remaining failures are fixed or skipped. | |
| continue-on-error: true | |
| if: (needs.Preconditions.outputs.lastCommitIsAutoCommit != 'true' || needs.Preconditions.outputs.lastCommitCreatedBeforeSeconds > 300) && needs.Changes.outputs.libred == 'true' | |
| strategy: | |
| fail-fast: false | |
| matrix: | |
| os: | |
| - ubuntu-latest | |
| - windows-latest | |
| - macos-latest | |
| # ARM64 legs. LibRed is fully managed with no ACE dependency, so these are the ones that | |
| # actually prove the cross-platform claim on a non-x64 architecture. Excludes LibRedAccess, | |
| # which cross-checks against the real Access engine and so needs Windows x64 with ACE. | |
| - ubuntu-24.04-arm | |
| - windows-11-arm | |
| runs-on: ${{ matrix.os }} | |
| steps: | |
| - name: Checkout | |
| uses: actions/checkout@v5 | |
| # Defender scans every .accdb these suites write; see the action for the measurement. | |
| - name: Exclude test files from Defender | |
| uses: ./.github/actions/exclude-defender | |
| - name: Install .NET SDK | |
| uses: actions/setup-dotnet@v5 | |
| with: | |
| global-json-file: global.json | |
| # No Access engine on ANY leg now. Windows used to install ACE as a control, on the reasoning that a | |
| # test failing only off Windows would be a real cross-platform gap - but all three legs have since | |
| # agreed exactly (35,578 passed / 179 failed / 2,016 skipped), so nothing here needs ACE and the | |
| # control has served its purpose. LibRedAccess still installs it, which is where the cross-checks | |
| # against the real engine belong. | |
| - name: 'Run Tests: EFCore.LibRed.FunctionalTests' | |
| if: env.skipTests != 'true' | |
| run: dotnet test test/EFCore.LibRed.FunctionalTests --configuration ${{ env.buildConfiguration }} -p:FixedTestOrder=${{ env.deterministicTests }} --blame-hang-timeout 10m | |
| # The same specification suite against extended mode, where the generator emits standard SQL instead of | |
| # Jet dialect workarounds. It has its own baselines, so it is a separate project rather than a matrix leg. | |
| # always(), so a failure in the compat suite above does not skip this one. | |
| - name: 'Run Tests: EFCore.LibRed.Extended.FunctionalTests' | |
| if: always() && env.skipTests != 'true' | |
| run: dotnet test test/EFCore.LibRed.Extended.FunctionalTests --configuration ${{ env.buildConfiguration }} -p:FixedTestOrder=${{ env.deterministicTests }} --blame-hang-timeout 10m | |
| MergeArtifacts: | |
| needs: BuildAndTest | |
| if: always() | |
| outputs: | |
| testResultsAvailable: ${{ steps.MergeTestResults.conclusion == 'success' }} | |
| greenTestsAvailable: ${{ steps.MergeGreenTests.conclusion == 'success' }} | |
| runs-on: ubuntu-latest | |
| steps: | |
| - name: 'Check Test Results Artifacts' | |
| id: CheckTestResultsArtifacts | |
| uses: actions/github-script@v8 | |
| with: | |
| script: | | |
| var allArtifacts = await github.rest.actions.listWorkflowRunArtifacts({ | |
| owner: context.repo.owner, | |
| repo: context.repo.repo, | |
| run_id: '${{ github.run_id }}', | |
| }); | |
| var artifacts = allArtifacts.data.artifacts.filter((artifact) => { | |
| return artifact.name.startsWith("test-results_"); | |
| }); | |
| if (artifacts.length > 0) { | |
| core.setOutput('artifactsAvailable', 'true'); | |
| console.log('Test results artifacts found.'); | |
| } | |
| - name: 'Merge Test Results' | |
| id: MergeTestResults | |
| if: steps.CheckTestResultsArtifacts.outputs.artifactsAvailable == 'true' | |
| uses: actions/upload-artifact/merge@v6 | |
| with: | |
| name: test-results | |
| pattern: test-results_* | |
| delete-merged: true | |
| - name: 'Check Green Tests Artifacts' | |
| id: CheckGreenTestsArtifacts | |
| uses: actions/github-script@v8 | |
| with: | |
| script: | | |
| var allArtifacts = await github.rest.actions.listWorkflowRunArtifacts({ | |
| owner: context.repo.owner, | |
| repo: context.repo.repo, | |
| run_id: '${{ github.run_id }}', | |
| }); | |
| var artifacts = allArtifacts.data.artifacts.filter((artifact) => { | |
| return artifact.name.startsWith("green-tests_"); | |
| }); | |
| if (artifacts.length > 0) { | |
| core.setOutput('artifactsAvailable', 'true'); | |
| console.log('Green Tests Artifacts found.'); | |
| } | |
| - name: 'Merge Green Tests' | |
| id: MergeGreenTests | |
| if: steps.CheckGreenTestsArtifacts.outputs.artifactsAvailable == 'true' | |
| uses: actions/upload-artifact/merge@v6 | |
| with: | |
| name: green-tests | |
| pattern: green-tests_* | |
| delete-merged: true | |
| NuGet: | |
| if: (github.event_name == 'push' || github.event_name == 'release') && github.repository == 'CirrusRedOrg/EntityFrameworkCore.Jet' | |
| runs-on: ubuntu-latest | |
| steps: | |
| - name: Checkout | |
| uses: actions/checkout@v5 | |
| - name: Setup .NET SDK | |
| uses: actions/setup-dotnet@v5 | |
| with: | |
| global-json-file: global.json | |
| - name: .NET Information | |
| shell: pwsh | |
| run: | | |
| dotnet --info | |
| - name: NuGet Pack | |
| shell: pwsh | |
| run: | | |
| $officialBuild = '${{ github.ref }}' -match '(?<=^refs/tags/v)\d+\.\d+\.\d+.*$' | |
| $officialVersion = $Matches.0 | |
| $wipBuild = '${{ github.ref }}' -match '^refs/heads/.*-wip$' | |
| $ciBuildOnly = $wipBuild -or ('${{ github.ref }}' -match '^refs/heads/(?:master|.*-servicing)$') | |
| $continuousIntegrationTimestamp = Get-Date -Format yyyyMMddHHmmss | |
| $buildSha = '${{ github.sha }}'.SubString(0, 7); | |
| $pack = $officialBuild -or $ciBuildOnly | |
| $pushToAzureArtifacts = $pack | |
| $pushToMygetOrg = $pack | |
| $pushToNugetOrg = $pack -and $officialBuild | |
| echo "pushToAzureArtifacts: $pushToAzureArtifacts" | |
| echo "pushToMygetOrg: $pushToMygetOrg" | |
| echo "pushToNugetOrg: $pushToNugetOrg" | |
| echo "officialBuild: $officialBuild" | |
| echo "officialVersion: $officialVersion" | |
| echo "wipBuild: $wipBuild" | |
| echo "ciBuildOnly: $ciBuildOnly" | |
| echo "continuousIntegrationTimestamp: $continuousIntegrationTimestamp" | |
| echo "buildSha: $buildSha" | |
| echo "pack: $pack" | |
| if ($pack) | |
| { | |
| $projectFiles = Get-ChildItem src/*/*.csproj -Recurse | % { $_.FullName } | |
| $combinations = @('default', @('Release')), @('withPdbs', @('Release', 'Debug')) #, @('embeddedPdbs', @('Release', 'Debug')) | |
| foreach ($combination in $combinations) | |
| { | |
| $type = $combination[0] | |
| $configurations = $combination[1] | |
| foreach ($configuration in $configurations) | |
| { | |
| $arguments = 'pack', '-c', $configuration, '-o', "nupkgs/$configuration/$type", '-p:ContinuousIntegrationBuild=true' | |
| if ($officialBuild) | |
| { | |
| $arguments += "-p:OfficialVersion=$officialVersion" | |
| } | |
| if ($ciBuildOnly) | |
| { | |
| $arguments += "-p:ContinuousIntegrationTimestamp=$continuousIntegrationTimestamp" | |
| $arguments += "-p:BuildSha=$buildSha" | |
| } | |
| switch ($type) | |
| { | |
| 'withPdbs' { $arguments += '-p:PackPdb=true', '-p:IncludeSymbols=false' } | |
| 'embeddedPdbs' { $arguments += '-p:DebugType=embedded', '-p:IncludeSymbols=false' } | |
| } | |
| foreach ($projectFile in $projectFiles) | |
| { | |
| echo "Type: $type, Configuration: $configuration, Project: $projectFile" | |
| echo "Pack command: dotnet $(($arguments + $projectFile) -join ' ')" | |
| & dotnet ($arguments + $projectFile) | |
| } | |
| } | |
| } | |
| } | |
| echo "pushToAzureArtifacts=$pushToAzureArtifacts" >> $env:GITHUB_ENV | |
| echo "pushToMygetOrg=$pushToMygetOrg" >> $env:GITHUB_ENV | |
| echo "pushToNugetOrg=$pushToNugetOrg" >> $env:GITHUB_ENV | |
| - name: Upload Artifacts | |
| uses: actions/upload-artifact@v6 | |
| with: | |
| name: nupkgs | |
| path: nupkgs | |
| - name: "NuGet Push - myget.org - Debug" | |
| if: ${{ env.pushToMygetOrg == 'true' }} | |
| working-directory: nupkgs | |
| shell: pwsh | |
| run: dotnet nuget push './Debug/withPdbs/**/*.nupkg' --api-key '${{ secrets.MYGETORG_CIRRUSRED_ALLPACKAGES_DEBUG_PUSHNEW }}' --source 'https://www.myget.org/F/cirrusred-debug/api/v3/index.json' --skip-duplicate | |
| - name: "NuGet Push - myget.org - Release" | |
| if: ${{ env.pushToMygetOrg == 'true' }} | |
| working-directory: nupkgs | |
| shell: pwsh | |
| run: dotnet nuget push './Release/default/**/*.nupkg' --api-key '${{ secrets.MYGETORG_CIRRUSRED_ALLPACKAGES_PUSHNEW }}' --source 'https://www.myget.org/F/cirrusred/api/v3/index.json' --skip-duplicate | |
| - name: "NuGet Push - nuget.org - Release" | |
| if: ${{ env.pushToNugetOrg == 'true' }} | |
| working-directory: nupkgs | |
| shell: pwsh | |
| run: dotnet nuget push './Release/default/**/*.nupkg' --api-key '${{ secrets.NUGETORG_EFCOREJET_ALLPACKAGES_PUSHNEW }}' --source 'https://api.nuget.org/v3/index.json' --skip-duplicate |