Enhance public API and add trimming compatibility attributes #246
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: CI | |
| on: | |
| pull_request: | |
| branches: [ master, develop ] | |
| push: | |
| branches: [ master ] | |
| concurrency: | |
| group: ci-${{ github.workflow }}-${{ github.ref }} | |
| cancel-in-progress: true | |
| permissions: | |
| contents: read | |
| jobs: | |
| test: | |
| name: Build & Test (${{ matrix.os }}) | |
| runs-on: ${{ matrix.os }} | |
| strategy: | |
| fail-fast: false | |
| matrix: | |
| os: [ubuntu-latest, windows-latest, macos-latest] | |
| steps: | |
| - name: Checkout | |
| uses: actions/checkout@v7 | |
| - name: Setup .NET | |
| uses: actions/setup-dotnet@v6 | |
| with: | |
| dotnet-version: | | |
| 8.0.x | |
| 10.0.x | |
| - name: Cache NuGet packages | |
| uses: actions/cache@v6 | |
| with: | |
| path: ~/.nuget/packages | |
| key: ${{ runner.os }}-nuget-${{ hashFiles('**/*.csproj', '**/Directory.Build.props') }} | |
| restore-keys: | | |
| ${{ runner.os }}-nuget- | |
| - name: Restore | |
| run: dotnet restore ExcelReader.slnx | |
| - name: Build (Release) | |
| run: dotnet build ExcelReader.slnx --configuration Release --no-restore -p:DeterministicSourcePaths=false | |
| - name: Verify formatting (whitespace) | |
| if: matrix.os == 'ubuntu-latest' | |
| run: dotnet format whitespace ExcelReader.slnx --verify-no-changes | |
| - name: Test (Release) + collect coverage | |
| run: >- | |
| dotnet test --project tests/ExcelReader.Tests/ExcelReader.Tests.csproj | |
| --results-directory ./TestResults | |
| --configuration Release | |
| --verbosity normal | |
| --no-build | |
| -- | |
| --report-xunit-trx | |
| --coverage | |
| --coverage-output-format cobertura | |
| - name: Upload test results | |
| if: always() | |
| uses: actions/upload-artifact@v7 | |
| with: | |
| name: test-results-${{ matrix.os }} | |
| path: ./TestResults/**/*.trx | |
| if-no-files-found: ignore | |
| - name: Upload coverage to Codecov | |
| if: matrix.os == 'ubuntu-latest' | |
| uses: codecov/codecov-action@v7 | |
| with: | |
| token: ${{ secrets.CODECOV_TOKEN }} | |
| files: ./TestResults/*.cobertura.xml | |
| fail_ci_if_error: false | |
| test-simd-fallbacks: | |
| name: Build & Test (${{ matrix.name }}) | |
| runs-on: ubuntu-latest | |
| strategy: | |
| fail-fast: false | |
| matrix: | |
| include: | |
| # Vector256 off, Vector128 still accelerated: exercises the SSE2 path on an AVX2 runner. | |
| - name: sse2-only | |
| enableAVX2: '0' | |
| enableAVX512F: '0' | |
| enableHWIntrinsic: '1' | |
| # No hardware intrinsics at all: exercises the scalar fallback end to end. | |
| - name: no-simd | |
| enableAVX2: '1' | |
| enableAVX512F: '1' | |
| enableHWIntrinsic: '0' | |
| env: | |
| DOTNET_EnableAVX2: ${{ matrix.enableAVX2 }} | |
| DOTNET_EnableAVX512F: ${{ matrix.enableAVX512F }} | |
| DOTNET_EnableHWIntrinsic: ${{ matrix.enableHWIntrinsic }} | |
| steps: | |
| - name: Checkout | |
| uses: actions/checkout@v7 | |
| - name: Setup .NET | |
| uses: actions/setup-dotnet@v6 | |
| with: | |
| dotnet-version: | | |
| 8.0.x | |
| 10.0.x | |
| - name: Cache NuGet packages | |
| uses: actions/cache@v6 | |
| with: | |
| path: ~/.nuget/packages | |
| key: ${{ runner.os }}-nuget-${{ hashFiles('**/*.csproj', '**/Directory.Build.props') }} | |
| restore-keys: | | |
| ${{ runner.os }}-nuget- | |
| - name: Restore | |
| run: dotnet restore ExcelReader.slnx | |
| - name: Build (Release) | |
| run: dotnet build ExcelReader.slnx --configuration Release --no-restore -p:DeterministicSourcePaths=false | |
| - name: Test (Release) | |
| run: >- | |
| dotnet test --project tests/ExcelReader.Tests/ExcelReader.Tests.csproj | |
| --configuration Release | |
| --verbosity normal | |
| --no-build | |
| aot-sanity: | |
| name: AOT/trim sanity (win-x64) | |
| runs-on: windows-latest | |
| steps: | |
| - name: Checkout | |
| uses: actions/checkout@v7 | |
| - name: Setup .NET | |
| uses: actions/setup-dotnet@v6 | |
| with: | |
| dotnet-version: | | |
| 8.0.x | |
| 10.0.x | |
| - name: Cache NuGet packages | |
| uses: actions/cache@v6 | |
| with: | |
| path: ~/.nuget/packages | |
| key: ${{ runner.os }}-nuget-${{ hashFiles('**/*.csproj', '**/Directory.Build.props') }} | |
| restore-keys: | | |
| ${{ runner.os }}-nuget- | |
| - name: Restore | |
| run: dotnet restore ExcelReader.slnx | |
| # Any IL2xxx (trim) or IL3xxx (AOT) diagnostic here is a build error (TrimmerSingleWarn=false | |
| # in the project so none of them get collapsed into one hidden summary line). This is the one | |
| # thing that actually proves the mapped read path never reaches ExcelParser<T>'s reflection. | |
| - name: Publish ExcelReader.AotSanity (PublishAot) | |
| run: dotnet publish tests/ExcelReader.AotSanity/ExcelReader.AotSanity.csproj -c Release -r win-x64 | |
| - name: Run published binary | |
| run: .\tests\ExcelReader.AotSanity\bin\Release\net10.0\win-x64\publish\ExcelReader.AotSanity.exe | |
| # R-A6: the generator is packed into ExcelReader.Core's nupkg via a hardcoded bin/ path | |
| # (ExcelReader.Core.csproj's `None Include`), which is fragile to configuration/TFM drift with | |
| # no build error if it silently stops matching — a consumer would only find out when their own | |
| # [ExcelSerializable] model fails with "does not implement IExcelRowMap<T>", with nothing pointing | |
| # at the real cause. This step is what actually catches that drift, by unzipping the real .nupkg | |
| # release.yml would ship and checking analyzers/dotnet/cs/ExcelReader.Generator.dll is in it. | |
| - name: Pack and verify the generator ships inside the nupkg | |
| shell: pwsh | |
| run: | | |
| dotnet pack src/ExcelReader.Core/ExcelReader.Core.csproj -c Release -o ./artifacts | |
| $pkg = Get-ChildItem ./artifacts/*.nupkg | Select-Object -First 1 | |
| Add-Type -AssemblyName System.IO.Compression.FileSystem | |
| $zip = [System.IO.Compression.ZipFile]::OpenRead($pkg.FullName) | |
| try { | |
| $entry = $zip.Entries | Where-Object { $_.FullName -eq 'analyzers/dotnet/cs/ExcelReader.Generator.dll' } | |
| } finally { | |
| $zip.Dispose() | |
| } | |
| if (-not $entry) { | |
| throw "ExcelReader.Generator.dll is missing from analyzers/dotnet/cs in $($pkg.Name) — the generator will not reach consumers of this package." | |
| } | |
| audit: | |
| name: Dependency audit | |
| runs-on: ubuntu-latest | |
| steps: | |
| - uses: actions/checkout@v7 | |
| - uses: actions/setup-dotnet@v6 | |
| with: | |
| dotnet-version: '10.0.x' | |
| - name: Restore | |
| run: dotnet restore ExcelReader.slnx | |
| - name: Check for vulnerable packages | |
| run: | | |
| echo "Scanning for known-vulnerable packages..." | |
| output=$(dotnet list ExcelReader.slnx package --vulnerable --include-transitive) | |
| echo "$output" | |
| if echo "$output" | grep -q -E '\b(High|Critical)\b'; then | |
| echo "::error::High or Critical severity vulnerability found in dependencies." | |
| exit 1 | |
| fi |