Skip to content

Commit 4e5e34c

Browse files
authored
chore(deps): bump the safe dependency lot, with the Hangfire family in lockstep (#266)
* chore(deps): bump the safe dependency lot, with the Hangfire family in lockstep All eleven Dependabot PRs (#241-#251) were closed unmerged, so the bumps are redone here as one verified change. This is the lot where the new version is a patch or minor within the same major; the major jumps (Npgsql 9->10, Microsoft.Data.Sqlite 9->10, Microsoft.Data.SqlClient 5->7, TestHost 8->10, Aspire 9.5->13.4) are deliberately left out and assessed separately. Hangfire.Core, Hangfire.SqlServer and Hangfire.AspNetCore move together to 1.8.24. Hangfire.NetCore arrives transitively and pins Hangfire.Core to an exact version, so bumping any one member alone fails restore with NU1608 — which is why #246 and #247 were red and could never have gone green on their own. dependabot.yml now groups Hangfire* so the family only ever travels as a unit. Microsoft.AspNetCore.TestHost goes to 8.0.29 rather than the available 10.0.10: the test projects target net8.0, so staying in the 8.x servicing line is the bump that belongs here. DocumentFormat.OpenXml 3.1.1 -> 3.5.1 made WorkbookPart.Workbook nullable, which TreatWarningsAsErrors turned into a build failure in XlsxRowReader. It is now checked rather than assumed; the existing "contains no worksheets" error covers that case. Verified after a --no-incremental rebuild: Core 303, AspNetCore 159, UI (bUnit 2.9) 245, WebUi E2E (Playwright 1.61) 24 passed / 0 skipped with NEOREPORTS_REQUIRE_BROWSER=1, Jobs 34, Sources.Xlsx 32, Formats.Xlsx 7, Formats.Csv 5, Destinations.S3 3, Destinations.Local 14 — 0 failures. * chore(deps): use an explicit type on the OpenXml nullability guard Sonar's new-code maintainability gate is a debt ratio, and this PR changes exactly three lines of C#, so a single 'use explicit type instead of var' on one of them was enough to take the rating to 3. Sheet[]? is also the clearer read next to the null-conditional chain that produces it. * fix(sources): validate XlsxRowReader's arguments before the iterator starts `ReadRows` contains `yield`, so none of its body — including `ArgumentNullException.ThrowIfNull(stream)` — executed until the caller's first MoveNext. A null stream therefore surfaced from inside the enumeration, with a stack that no longer pointed at the call that passed it. Splitting the eager wrapper from the iterator makes the check fire where the mistake was made. This is what SonarCloud's new-code maintainability gate flagged on the dependency-bump PR. The line is pre-existing (63deea1, 2026-07-17) and Sonar counts it as new because the master baseline has been broken since the 50k-LOC free-tier cap hit on 2026-07-12 — but the finding itself is real, and the file already had to change here for the OpenXml nullability guard, so it is fixed rather than worked around. No test: XlsxRowReader is internal with no InternalsVisibleTo, and the public surface takes a file path or S3 config rather than a Stream, so the null path is not reachable from outside. The existing 32 tests pass unchanged, which is what confirms the split did not alter enumeration semantics.
1 parent 8063125 commit 4e5e34c

3 files changed

Lines changed: 34 additions & 14 deletions

File tree

.github/dependabot.yml

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,13 @@ updates:
1313
microsoft-extensions:
1414
patterns:
1515
- "Microsoft.Extensions.*"
16+
# Not noise-reduction: a CORRECTNESS requirement. Hangfire.NetCore arrives transitively and
17+
# pins Hangfire.Core to an exact version, so bumping any one member alone fails restore with
18+
# NU1608 — PRs #246 and #247 could never go green on their own, whatever CI did. The family
19+
# only moves as a unit.
20+
hangfire:
21+
patterns:
22+
- "Hangfire*"
1623
test-tooling:
1724
patterns:
1825
- "xunit*"

build/Directory.Packages.props

Lines changed: 13 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66

77
<ItemGroup>
88
<!-- Core -->
9-
<PackageVersion Include="Polly.Core" Version="8.6.6" />
9+
<PackageVersion Include="Polly.Core" Version="8.7.0" />
1010
<PackageVersion Include="Microsoft.Extensions.Logging.Abstractions" Version="10.0.10" />
1111
<PackageVersion Include="Microsoft.Extensions.DependencyInjection.Abstractions" Version="10.0.10" />
1212
<PackageVersion Include="Microsoft.Extensions.DependencyInjection" Version="10.0.10" />
@@ -19,42 +19,42 @@
1919
<PackageVersion Include="Microsoft.Data.SqlClient" Version="5.2.2" />
2020
<PackageVersion Include="Npgsql" Version="9.0.5" />
2121
<PackageVersion Include="MySqlConnector" Version="2.6.1" />
22-
<PackageVersion Include="Oracle.ManagedDataAccess.Core" Version="23.26.200" />
22+
<PackageVersion Include="Oracle.ManagedDataAccess.Core" Version="23.26.300" />
2323
<PackageVersion Include="Microsoft.Data.Sqlite" Version="9.0.18" />
2424
<PackageVersion Include="Snowflake.Data" Version="5.7.0" />
2525
<PackageVersion Include="MongoDB.Driver" Version="3.10.0" />
26-
<PackageVersion Include="ClosedXML" Version="0.105.0" />
27-
<PackageVersion Include="DocumentFormat.OpenXml" Version="3.1.1" />
26+
<PackageVersion Include="ClosedXML" Version="0.105.1" />
27+
<PackageVersion Include="DocumentFormat.OpenXml" Version="3.5.1" />
2828
<PackageVersion Include="Parquet.Net" Version="6.0.3" />
29-
<PackageVersion Include="AWSSDK.S3" Version="4.0.100.2" />
29+
<PackageVersion Include="AWSSDK.S3" Version="4.0.101.7" />
3030

3131
<!-- Scheduling -->
3232
<PackageVersion Include="Cronos" Version="0.13.0" />
3333

3434
<!-- Jobs -->
35-
<PackageVersion Include="Hangfire.Core" Version="1.8.14" />
36-
<PackageVersion Include="Hangfire.SqlServer" Version="1.8.14" />
37-
<PackageVersion Include="Hangfire.AspNetCore" Version="1.8.14" />
35+
<PackageVersion Include="Hangfire.Core" Version="1.8.24" />
36+
<PackageVersion Include="Hangfire.SqlServer" Version="1.8.24" />
37+
<PackageVersion Include="Hangfire.AspNetCore" Version="1.8.24" />
3838
<PackageVersion Include="Hangfire.InMemory" Version="1.0.0" />
3939

4040
<!-- Tests -->
4141
<PackageVersion Include="xunit" Version="2.9.3" />
4242
<PackageVersion Include="xunit.runner.visualstudio" Version="3.1.5" />
4343
<PackageVersion Include="Microsoft.NET.Test.Sdk" Version="18.8.1" />
44-
<PackageVersion Include="Shouldly" Version="4.2.1" />
45-
<PackageVersion Include="Microsoft.Playwright" Version="1.56.0" />
44+
<PackageVersion Include="Shouldly" Version="4.3.0" />
45+
<PackageVersion Include="Microsoft.Playwright" Version="1.61.0" />
4646
<PackageVersion Include="NSubstitute" Version="6.0.0" />
4747
<PackageVersion Include="Testcontainers.MsSql" Version="4.13.0" />
4848
<PackageVersion Include="Testcontainers.PostgreSql" Version="4.13.0" />
4949
<PackageVersion Include="Testcontainers.MySql" Version="4.13.0" />
5050
<PackageVersion Include="Testcontainers.Oracle" Version="4.13.0" />
5151
<PackageVersion Include="Testcontainers.MongoDb" Version="4.13.0" />
5252
<PackageVersion Include="Xunit.SkippableFact" Version="1.5.61" />
53-
<PackageVersion Include="Microsoft.AspNetCore.TestHost" Version="8.0.11" />
54-
<PackageVersion Include="bunit" Version="2.6.2" />
53+
<PackageVersion Include="Microsoft.AspNetCore.TestHost" Version="8.0.29" />
54+
<PackageVersion Include="bunit" Version="2.9.0" />
5555

5656
<!-- Benchmarks -->
57-
<PackageVersion Include="BenchmarkDotNet" Version="0.14.0" />
57+
<PackageVersion Include="BenchmarkDotNet" Version="0.15.8" />
5858

5959
<!-- Samples / Aspire (Epic H) — 9.5.2 is the last Aspire line targeting net8.0/net9.0;
6060
Aspire 13.x's AppHost SDK forces net10.0, which would be inconsistent with every other

src/Sources/NeoReports.Sources.Xlsx/XlsxRowReader.cs

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -51,8 +51,18 @@ internal static class XlsxRowReader
5151
public static IEnumerable<object?[]> ReadRows(
5252
Stream stream, string? sheetName, CancellationToken cancellationToken)
5353
{
54+
// Validated here rather than inside the iterator below: a method containing `yield` does not
55+
// execute any of its body until the first MoveNext, so this check used to fire from inside
56+
// the enumeration — with a stack that no longer points at the call that passed the null.
5457
ArgumentNullException.ThrowIfNull(stream);
5558

59+
return Enumerate(stream, sheetName, cancellationToken);
60+
}
61+
62+
/// <summary>The iterator half of <see cref="ReadRows"/>; arguments are already validated.</summary>
63+
private static IEnumerable<object?[]> Enumerate(
64+
Stream stream, string? sheetName, CancellationToken cancellationToken)
65+
{
5666
using var document = SpreadsheetDocument.Open(stream, isEditable: false);
5767
var workbookPart = document.WorkbookPart
5868
?? throw new InvalidOperationException("The XLSX package has no workbook part.");
@@ -204,7 +214,10 @@ internal static int ColumnIndex(string? cellReference)
204214
/// <summary>Finds the worksheet part by sheet name, or the first sheet when no name is given.</summary>
205215
private static WorksheetPart ResolveWorksheetPart(WorkbookPart workbookPart, string? sheetName)
206216
{
207-
var sheets = workbookPart.Workbook.Sheets?.Elements<Sheet>().ToArray();
217+
// Workbook became nullable in DocumentFormat.OpenXml 3.5 (it is populated lazily and a
218+
// malformed package can genuinely lack it), so it is checked rather than assumed — the
219+
// existing "no worksheets" message covers that case correctly either way.
220+
Sheet[]? sheets = workbookPart.Workbook?.Sheets?.Elements<Sheet>().ToArray();
208221
if (sheets is null || sheets.Length == 0)
209222
throw new InvalidOperationException("The XLSX workbook contains no worksheets.");
210223

0 commit comments

Comments
 (0)