Skip to content

release: v1.0.0#11

Merged
jkindrix merged 1 commit into
mainfrom
release/v1.0.0
May 20, 2026
Merged

release: v1.0.0#11
jkindrix merged 1 commit into
mainfrom
release/v1.0.0

Conversation

@jkindrix

Copy link
Copy Markdown
Owner

v1.0.0 release PR

Executes the v1.0 release-PR checklist from docs/roadmap.md.

Checklist

  • PublicAPI flip — all 380 entries moved from Unshipped.txtShipped.txt in src/NetXlsx/. Unshipped reset to header-only.
  • PublicApiSnapshotTests baseline — unchanged (TFM-invariant; was already in sync).
  • net9.0 drop per I24Directory.Build.props, CI workflows, docs/design.md decision Bump the test-stack group with 1 update #12.
  • CHANGELOG breaking-change banner — top of the new [1.0.0] entry calls out the net9.0 drop with migration guidance.
  • Version tag — pushed after this PR merges, against the merge commit (so MinVer picks it up). v1.0.0 matches the release workflow's v* trigger.
  • NUGET_API_KEY secretNOT YET SET. If we want v1.0.0 to publish synchronously with the tag, set this in repo Settings → Secrets and variables → Actions before pushing the tag. Otherwise the release workflow skips the NuGet push and just uploads .nupkg artifacts + creates the GH Release.
  • Stale-count sweep — README updated from "434 × 3 = 1,302" to "434 × 2 = 868"; TFM intro line updated to "net8.0 and net10.0 (both LTS)".
  • Three v1.0 ship-blockers landed before this PR: headless-no-fonts CI gate (66e4f4d), benchmark regression CI gate (97b981f), full preservation fixture (4dfb001).

Validation

868 test runs (434 per TFM × 2 TFMs) green locally on net8.0 + net10.0. Build clean, 0 warnings, 0 errors. CI matrix on this PR will verify the same across ubuntu-latest + windows-latest.

After merge

  1. git tag v1.0.0 from the merge commit, git push origin v1.0.0.
  2. The release workflow fires on the tag and either publishes to NuGet (if NUGET_API_KEY is set) or uploads artifacts + creates the GH Release without the publish.
  3. The [Unreleased] slot in CHANGELOG.md is empty and ready for the next slice.

Executes the v1.0 release-PR checklist from docs/roadmap.md verbatim:

1. PublicAPI flip — moved all 380 entries from
   src/NetXlsx/PublicAPI.Unshipped.txt into PublicAPI.Shipped.txt.
   Unshipped reset to just the `#nullable enable` header. Any
   post-v1.0 surface addition now goes through the standard
   Unshipped-then-Shipped-at-next-tag flow.

2. PublicApiSnapshotTests baseline — unchanged (the test is
   TFM-invariant; it asserts the public type list and was already
   in sync with the Unshipped entries).

3. net9.0 drop per decision I24. After 2026-05-12 STS EOS,
   net9.0 leaves the TargetFrameworks list:
   - Directory.Build.props: net8.0;net9.0;net10.0 -> net8.0;net10.0
   - .github/workflows/{ci,release,bench}.yml: removed 9.0.x from
     setup-dotnet matrices
   - docs/design.md decision #12 updated
   Consumers on net9.0 install the net8.0 build via the standard
   TFM fallback — no API change.

4. CHANGELOG v1.0.0 entry with explicit BREAKING CHANGES banner
   covering the net9.0 drop, plus a Highlights section
   summarizing what shipped (style-pool dedup, source-gen typed
   mapping, type-level streaming split, OPC preservation
   guarantee, build-time AOT/trim guard, MissingFontException).
   Slice-by-slice history retained below the highlights.

5. Stale-count sweep — README's "434 tests/TFM × 3 TFMs = 1,302"
   updated to "434 × 2 = 868" post-drop. TFM mention in the
   README intro updated to "net8.0 and net10.0 (both LTS)".

6. All three v1.0 ship-blockers confirmed landed in main before
   this PR: headless-no-fonts CI gate (66e4f4d), benchmark
   regression CI gate (97b981f), full preservation fixture
   (4dfb001).

Validation: 868 test runs (434/TFM x 2 TFMs) green locally on
net8.0 + net10.0. Build clean, 0 warnings, 0 errors.

Note before tag: NUGET_API_KEY secret is not yet set in repo
settings. The release workflow has a graceful skip path
(uploads .nupkg artifacts to the workflow run, creates the GH
Release, but does not push to nuget.org). If we want v1.0.0
to publish synchronously with the tag, set NUGET_API_KEY first.
@jkindrix

Copy link
Copy Markdown
Owner Author

Bench-gate override — both initial run and re-run flagged ReadBenchmarks.OpenAndReadColumnSum +18% (+18.16% then +18.02%). The other four benchmarks all stabilized within ±5%.

Root-cause analysis: this PR's diff is zero runtime code. The src/ changes are:

  • PublicAPI.Shipped.txt populated (build-time metadata only)
  • PublicAPI.Unshipped.txt reset to header (same)
  • No .cs files modified

The bench workflow's cache key includes hashFiles('src/**'). Modifying PublicAPI.Shipped.txt changes that hash → exact-key cache miss → restore-keys fallback to the previous bench cache from main. That previous cache was populated on a different runner instance (different image generation, different physical box, different time-of-day load). The +18% is the variance between runner instances, not the variance from this PR's changes.

This is a real flaw in the bench cache strategy — the src/** hash inclusion is too aggressive. Filed as a v1.1 follow-up: tighten the cache key to hash only src/**/*.cs so PublicAPI / CHANGELOG / docs changes don't invalidate the bench baseline.

Merging with admin override. Documented for the audit trail.

@jkindrix jkindrix merged commit 855c90d into main May 20, 2026
3 of 5 checks passed
@jkindrix jkindrix deleted the release/v1.0.0 branch May 20, 2026 21:25
jkindrix added a commit that referenced this pull request Jun 3, 2026
Implements SetAutoFilter / ClearAutoFilter / SetAutoFilterColumn /
ClearAutoFilterColumn / HasAutoFilter / AutoFilterRange on the SDK
engine (new OoxmlSheet.AutoFilter.cs), per decisions I-56 + I-66.

<autoFilter> is a 0..1 singleton in CT_Worksheet's strict sequence, so
the insert routes through OoxmlSchemaOrder.GetOrInsert (SDK-quirk #8).
Per-column criteria emit <filterColumn colId><customFilters [and]> with
1-2 <customFilter operator val> conditions, inserted before any
trailing sortState/extLst an opened file may carry.

Oracle-checked against the NPOI engine's emitted XML (quirk #11 habit):
SetAutoFilter also creates/updates Excel's hidden built-in
_xlnm._FilterDatabase defined name (new internal
OoxmlWorkbook.SetFilterDatabaseName — bypasses user-name validation and
the uniqueness rule, since built-in names repeat per localSheetId); the
refers-to keeps the r1:r2 form with no 1x1 collapse and quotes the
sheet name when needed. Re-setting the range keeps existing
filterColumn entries; ClearAutoFilter leaves the stale name in place.
NPOI's showButton="1" is the OOXML default and is deliberately omitted.

Conformance: AutoFilterTests mirrors the NPOI-engine suite + the
oracle-pinned name/replace semantics; schema-gate fixtures incl. the
required open-mutate case (autoFilter inserts before an existing
mergeCells); cross-engine differential scenarios (filter state +
_FilterDatabase name, cleared state); and a corrupt @ref malformed-
input parity check (SDK-quirk #13 diligence).
jkindrix added a commit that referenced this pull request Jun 3, 2026
Implements ISheet.AddChart (all six ChartTypes) + IChart (Sheet/Type/
SetTitle) on the SDK engine: a ChartPart hung off the sheet's DrawingsPart,
referenced from an xdr:graphicFrame in a twoCellAnchor with the exclusive
end-cell convention (quirk #10 checked against the NPOI oracle, not assumed).
strCache/numCache snapshot the referenced cells at AddChart time with NPOI's
skip semantics (ptCount = full range; only type-matching cells get a pt).

The chart XML was oracle-dumped from the NPOI engine for all six types
before implementing (quirk #11). Documented conformance-positive divergences
(quirk #14): pie dPt list in CT_PieSer schema order (NPOI emits it after
val), no dangling pie axes, scatter plotted on two value axes (NPOI pairs a
catAx), nonzero cNvPr ids (NPOI emits id=0), editAs omitted (schema default).

IChart.Underlying (NPOI XSSFChart) throws NotSupportedException on the SDK
engine — the established escape-hatch divergence. New ChartTests (33) incl.
a cross-engine emission-projection parity test, plus two schema-gate
fixtures; all six chart types validate clean under Microsoft365.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant