Skip to content

Cache NuGet packages, enable lock files and package validation - #373

Merged
twcclegg merged 6 commits into
mainfrom
build/lockfile-and-cache
Aug 5, 2026
Merged

Cache NuGet packages, enable lock files and package validation#373
twcclegg merged 6 commits into
mainfrom
build/lockfile-and-cache

Conversation

@twcclegg

@twcclegg twcclegg commented Aug 5, 2026

Copy link
Copy Markdown
Owner

Three build/CI changes. No shipped code is affected.

build: cache nuget packages in ci and enable restore lock files

~/.nuget/packages is cached in the four workflows that run on every PR. Central Package Management
puts every version in one file, so the key is a hash of Directory.Packages.props plus the project
files.

Deliberately not added to publish_nuget.yml: the release path should resolve from nuget.org
rather than a mutable, branch-writable cache. A few seconds aren't worth putting a cache into the
supply chain of a published artifact.

build: enable package validation on the packable projects

Pack now fails on a breaking public API change, which turns "no breaking changes" from a policy into
a build gate. That matters most because releases are cut automatically by
create_new_release_on_new_metadata_update.yml with nobody reviewing the API surface.

PackageValidationBaselineVersion is intentionally unset. 9.0.36 ships a lib/net9.0/ asset this
package no longer produces, so baselining against it would flag the dropped target framework and
require a permanent suppression. Setting it to the first release without net9.0 avoids that
entirely. Until then validation still runs its within-package check, verifying every target
framework exposes a consistent public surface — which is how a net8-only public member would
otherwise slip in.

build: commit restore lock files and check them in ci

packages.lock.json for six projects, pinning the full transitive graph with content hashes, and
dotnet restore --locked-mode in CI so a restore can never quietly resolve a different transitive
version than the lock file records.

PhoneNumbers.Test and PhoneNumbers.Extensions.Test are opted out. Their TFM lists are
OS-conditional (netframework4.8 only on Windows), so a lock file generated on Linux omits a
framework a Windows contributor would restore — rewriting the file in normal mode and failing under
locked mode. A lock file whose contents depend on who restored it is worse than none, so those two
keep dynamic restore.

The files were generated by CI rather than locally: a temporary artifact-upload step ran on this
branch, and the step was removed once they were committed. That flow means refreshing them never
requires a local dotnet install.

Worth watching: the first Dependabot PR after this. If Dependabot doesn't update
packages.lock.json alongside Directory.Packages.props, its restore will fail under locked mode —
visibly, not silently. That's the point to add a dispatchable regeneration workflow, rather than
building one speculatively now.

@codecov

codecov Bot commented Aug 5, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 98.01%. Comparing base (aed9e7f) to head (7f795c5).

Additional details and impacted files
@@           Coverage Diff           @@
##             main     #373   +/-   ##
=======================================
  Coverage   98.01%   98.01%           
=======================================
  Files          39       39           
  Lines       52799    52799           
  Branches     1103     1103           
=======================================
  Hits        51751    51751           
  Misses        795      795           
  Partials      253      253           

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@github-actions

github-actions Bot commented Aug 5, 2026

Copy link
Copy Markdown

📊 Benchmark Results

Commit: 7f795c5 · Full run · Linux ubuntu-24.04-arm

Both sides were measured on the same runner in the same job, so the numbers are
comparable. Treat sub-percent differences as noise.

PR branch

BenchmarkDotNet v0.15.8, Linux Ubuntu 24.04.4 LTS (Noble Numbat)
Neoverse-N2, 4 physical cores
.NET SDK 10.0.302
  [Host]    : .NET 10.0.10 (10.0.10, 10.0.1026.32716), Arm64 RyuJIT armv8.0-a
  .NET 10.0 : .NET 10.0.10 (10.0.10, 10.0.1026.32716), Arm64 RyuJIT armv8.0-a

Job=.NET 10.0  Runtime=.NET 10.0  

Method PhoneNumberCount Mean Error StdDev Gen0 Allocated
InputDigitPerKeystroke 1000 4.651 ms 0.0354 ms 0.0276 ms 54.6875 3.87 MB

BenchmarkDotNet v0.15.8, Linux Ubuntu 24.04.4 LTS (Noble Numbat)
Neoverse-N2, 4 physical cores
.NET SDK 10.0.302
  [Host]     : .NET 10.0.10 (10.0.10, 10.0.1026.32716), Arm64 RyuJIT armv8.0-a
  Job-AMQORM : .NET 10.0.10 (10.0.10, 10.0.1026.32716), Arm64 RyuJIT armv8.0-a

Runtime=.NET 10.0  InvocationCount=1  IterationCount=20  
LaunchCount=1  RunStrategy=ColdStart  UnrollFactor=1  
WarmupCount=1  

Method Mean Error StdDev Allocated
CreateInstance 412.1 μs 138.9 μs 160.0 μs 119.48 KB
CreateInstanceAndLoadAllRegions 7,105.5 μs 391.6 μs 451.0 μs 1619.1 KB
FirstRegionLookup 470.3 μs 153.3 μs 176.5 μs 124.54 KB

BenchmarkDotNet v0.15.8, Linux Ubuntu 24.04.4 LTS (Noble Numbat)
Neoverse-N2, 4 physical cores
.NET SDK 10.0.302
  [Host]    : .NET 10.0.10 (10.0.10, 10.0.1026.32716), Arm64 RyuJIT armv8.0-a
  .NET 10.0 : .NET 10.0.10 (10.0.10, 10.0.1026.32716), Arm64 RyuJIT armv8.0-a

Job=.NET 10.0  Runtime=.NET 10.0  

Method PhoneNumberCount Mean Error StdDev Gen0 Allocated
ExtractPossibleNumber_CleanInput 1000 21.60 μs 0.022 μs 0.021 μs - -
ExtractPossibleNumber_WithLeadingJunk 1000 38.53 μs 0.057 μs 0.048 μs 0.6714 48360 B

BenchmarkDotNet v0.15.8, Linux Ubuntu 24.04.4 LTS (Noble Numbat)
Neoverse-N2, 4 physical cores
.NET SDK 10.0.302
  [Host]    : .NET 10.0.10 (10.0.10, 10.0.1026.32716), Arm64 RyuJIT armv8.0-a
  .NET 10.0 : .NET 10.0.10 (10.0.10, 10.0.1026.32716), Arm64 RyuJIT armv8.0-a

Job=.NET 10.0  Runtime=.NET 10.0  

Method PhoneNumberCount Mean Error StdDev Gen0 Allocated
FindNumbers_Valid 100 138.5 μs 0.22 μs 0.19 μs 0.9766 69.93 KB
FindNumbers_StrictGrouping 100 296.9 μs 1.02 μs 0.86 μs 1.4648 123.2 KB

BenchmarkDotNet v0.15.8, Linux Ubuntu 24.04.4 LTS (Noble Numbat)
Neoverse-N2, 4 physical cores
.NET SDK 10.0.302
  [Host]    : .NET 10.0.10 (10.0.10, 10.0.1026.32716), Arm64 RyuJIT armv8.0-a
  .NET 10.0 : .NET 10.0.10 (10.0.10, 10.0.1026.32716), Arm64 RyuJIT armv8.0-a

Job=.NET 10.0  Runtime=.NET 10.0  

Method PhoneNumberCount Mean Error StdDev Gen0 Allocated
GetDescriptionForNumber 1000 1,463.06 μs 8.936 μs 7.922 μs 1.9531 237.83 KB
GetDisplayCountry 1000 25.65 μs 0.030 μs 0.026 μs 0.0916 7.56 KB

BenchmarkDotNet v0.15.8, Linux Ubuntu 24.04.4 LTS (Noble Numbat)
Neoverse-N2, 4 physical cores
.NET SDK 10.0.302
  [Host]    : .NET 10.0.10 (10.0.10, 10.0.1026.32716), Arm64 RyuJIT armv8.0-a
  .NET 10.0 : .NET 10.0.10 (10.0.10, 10.0.1026.32716), Arm64 RyuJIT armv8.0-a

Job=.NET 10.0  Runtime=.NET 10.0  

Method PhoneNumberCount Mean Error StdDev Gen0 Allocated
ParseValidateAndFormatPhoneNumbers 1000 2.510 ms 0.0121 ms 0.0113 ms 7.8125 580.51 KB
ParseValidateAndFormatPhoneNumbers 10000 25.540 ms 0.0447 ms 0.0397 ms 62.5000 5798.53 KB
PR base

BenchmarkDotNet v0.15.8, Linux Ubuntu 24.04.4 LTS (Noble Numbat)
Neoverse-N2, 4 physical cores
.NET SDK 10.0.302
  [Host]    : .NET 10.0.10 (10.0.10, 10.0.1026.32716), Arm64 RyuJIT armv8.0-a
  .NET 10.0 : .NET 10.0.10 (10.0.10, 10.0.1026.32716), Arm64 RyuJIT armv8.0-a

Job=.NET 10.0  Runtime=.NET 10.0  

Method PhoneNumberCount Mean Error StdDev Gen0 Allocated
InputDigitPerKeystroke 1000 4.645 ms 0.0899 ms 0.0999 ms 54.6875 3.87 MB

BenchmarkDotNet v0.15.8, Linux Ubuntu 24.04.4 LTS (Noble Numbat)
Neoverse-N2, 4 physical cores
.NET SDK 10.0.302
  [Host]     : .NET 10.0.10 (10.0.10, 10.0.1026.32716), Arm64 RyuJIT armv8.0-a
  Job-AMQORM : .NET 10.0.10 (10.0.10, 10.0.1026.32716), Arm64 RyuJIT armv8.0-a

Runtime=.NET 10.0  InvocationCount=1  IterationCount=20  
LaunchCount=1  RunStrategy=ColdStart  UnrollFactor=1  
WarmupCount=1  

Method Mean Error StdDev Allocated
CreateInstance 398.2 μs 111.0 μs 127.8 μs 119.48 KB
CreateInstanceAndLoadAllRegions 7,096.3 μs 387.0 μs 445.7 μs 1619.1 KB
FirstRegionLookup 466.1 μs 154.8 μs 178.2 μs 124.54 KB

BenchmarkDotNet v0.15.8, Linux Ubuntu 24.04.4 LTS (Noble Numbat)
Neoverse-N2, 4 physical cores
.NET SDK 10.0.302
  [Host]    : .NET 10.0.10 (10.0.10, 10.0.1026.32716), Arm64 RyuJIT armv8.0-a
  .NET 10.0 : .NET 10.0.10 (10.0.10, 10.0.1026.32716), Arm64 RyuJIT armv8.0-a

Job=.NET 10.0  Runtime=.NET 10.0  

Method PhoneNumberCount Mean Error StdDev Gen0 Allocated
ExtractPossibleNumber_CleanInput 1000 21.62 μs 0.028 μs 0.026 μs - -
ExtractPossibleNumber_WithLeadingJunk 1000 38.01 μs 0.062 μs 0.055 μs 0.6714 48360 B

BenchmarkDotNet v0.15.8, Linux Ubuntu 24.04.4 LTS (Noble Numbat)
Neoverse-N2, 4 physical cores
.NET SDK 10.0.302
  [Host]    : .NET 10.0.10 (10.0.10, 10.0.1026.32716), Arm64 RyuJIT armv8.0-a
  .NET 10.0 : .NET 10.0.10 (10.0.10, 10.0.1026.32716), Arm64 RyuJIT armv8.0-a

Job=.NET 10.0  Runtime=.NET 10.0  

Method PhoneNumberCount Mean Error StdDev Gen0 Allocated
FindNumbers_Valid 100 139.9 μs 0.32 μs 0.28 μs 0.9766 69.93 KB
FindNumbers_StrictGrouping 100 308.6 μs 0.89 μs 0.79 μs 1.4648 123.2 KB

BenchmarkDotNet v0.15.8, Linux Ubuntu 24.04.4 LTS (Noble Numbat)
Neoverse-N2, 4 physical cores
.NET SDK 10.0.302
  [Host]    : .NET 10.0.10 (10.0.10, 10.0.1026.32716), Arm64 RyuJIT armv8.0-a
  .NET 10.0 : .NET 10.0.10 (10.0.10, 10.0.1026.32716), Arm64 RyuJIT armv8.0-a

Job=.NET 10.0  Runtime=.NET 10.0  

Method PhoneNumberCount Mean Error StdDev Gen0 Allocated
GetDescriptionForNumber 1000 1,446.44 μs 5.457 μs 4.838 μs 1.9531 237.83 KB
GetDisplayCountry 1000 21.15 μs 0.023 μs 0.019 μs 0.0916 7.56 KB

BenchmarkDotNet v0.15.8, Linux Ubuntu 24.04.4 LTS (Noble Numbat)
Neoverse-N2, 4 physical cores
.NET SDK 10.0.302
  [Host]    : .NET 10.0.10 (10.0.10, 10.0.1026.32716), Arm64 RyuJIT armv8.0-a
  .NET 10.0 : .NET 10.0.10 (10.0.10, 10.0.1026.32716), Arm64 RyuJIT armv8.0-a

Job=.NET 10.0  Runtime=.NET 10.0  

Method PhoneNumberCount Mean Error StdDev Gen0 Allocated
ParseValidateAndFormatPhoneNumbers 1000 2.532 ms 0.0101 ms 0.0089 ms 7.8125 580.51 KB
ParseValidateAndFormatPhoneNumbers 10000 24.419 ms 0.0722 ms 0.0603 ms 62.5000 5798.53 KB

@twcclegg
twcclegg marked this pull request as ready for review August 5, 2026 17:44
@twcclegg
twcclegg merged commit 90a5a61 into main Aug 5, 2026
8 checks passed
@twcclegg
twcclegg deleted the build/lockfile-and-cache branch August 5, 2026 17:47
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