From 1819f1175df7098a8196341a35d76a6f9cf6fb11 Mon Sep 17 00:00:00 2001 From: Daniel Bohlin Date: Sun, 26 Jul 2026 19:10:37 +0200 Subject: [PATCH 1/2] fix(pack): publish symbols as snupkg so they actually reach nuget.org MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit IncludeSymbols was on but SymbolPackageFormat was not set, so pack emitted the legacy `Foo..symbols.nupkg`. That filename still ends in `.nupkg`, so the release workflow's for pkg in ./artifacts/*.nupkg loop picked it up and pushed it as a *regular* package. nuget.org rejected it as a duplicate of the main package — same id, same version — and the `|| true` at the end of the push line swallowed the error, so every release went green while publishing no symbols at all. A `.snupkg` is not matched by that glob, and `dotnet nuget push` uploads it alongside its `.nupkg` automatically. The artifact step already uploads the whole ./artifacts directory, so the file survives the hand-off from the build job to the release job. No republish is needed; this takes effect on the next release. --- Tharga.Cache.Blazor/Tharga.Cache.Blazor.csproj | 4 ++++ Tharga.Cache.File/Tharga.Cache.File.csproj | 4 ++++ Tharga.Cache.Mcp/Tharga.Cache.Mcp.csproj | 6 +++++- Tharga.Cache.MongoDB/Tharga.Cache.MongoDB.csproj | 4 ++++ Tharga.Cache.Redis/Tharga.Cache.Redis.csproj | 4 ++++ Tharga.Cache/Tharga.Cache.csproj | 4 ++++ 6 files changed, 25 insertions(+), 1 deletion(-) diff --git a/Tharga.Cache.Blazor/Tharga.Cache.Blazor.csproj b/Tharga.Cache.Blazor/Tharga.Cache.Blazor.csproj index 384a02d..3c5c359 100644 --- a/Tharga.Cache.Blazor/Tharga.Cache.Blazor.csproj +++ b/Tharga.Cache.Blazor/Tharga.Cache.Blazor.csproj @@ -16,6 +16,10 @@ true true true + + snupkg 1701;1702;CS1591;CS0809 diff --git a/Tharga.Cache.File/Tharga.Cache.File.csproj b/Tharga.Cache.File/Tharga.Cache.File.csproj index cdb1b14..a9b645f 100644 --- a/Tharga.Cache.File/Tharga.Cache.File.csproj +++ b/Tharga.Cache.File/Tharga.Cache.File.csproj @@ -12,6 +12,10 @@ https://github.com/Tharga/Cache README.md true + + snupkg true true true diff --git a/Tharga.Cache.Mcp/Tharga.Cache.Mcp.csproj b/Tharga.Cache.Mcp/Tharga.Cache.Mcp.csproj index d84f08f..71b3d5b 100644 --- a/Tharga.Cache.Mcp/Tharga.Cache.Mcp.csproj +++ b/Tharga.Cache.Mcp/Tharga.Cache.Mcp.csproj @@ -1,4 +1,4 @@ - + net8.0;net9.0;net10.0 @@ -13,6 +13,10 @@ https://github.com/Tharga/Cache README.md true + + snupkg true true true diff --git a/Tharga.Cache.MongoDB/Tharga.Cache.MongoDB.csproj b/Tharga.Cache.MongoDB/Tharga.Cache.MongoDB.csproj index 3e839c6..cc29dcb 100644 --- a/Tharga.Cache.MongoDB/Tharga.Cache.MongoDB.csproj +++ b/Tharga.Cache.MongoDB/Tharga.Cache.MongoDB.csproj @@ -12,6 +12,10 @@ https://github.com/Tharga/Cache README.md true + + snupkg true true true diff --git a/Tharga.Cache.Redis/Tharga.Cache.Redis.csproj b/Tharga.Cache.Redis/Tharga.Cache.Redis.csproj index 2d419d8..d69689e 100644 --- a/Tharga.Cache.Redis/Tharga.Cache.Redis.csproj +++ b/Tharga.Cache.Redis/Tharga.Cache.Redis.csproj @@ -13,6 +13,10 @@ https://github.com/Tharga/Cache README.md true + + snupkg true true true diff --git a/Tharga.Cache/Tharga.Cache.csproj b/Tharga.Cache/Tharga.Cache.csproj index e32773b..c6054ca 100644 --- a/Tharga.Cache/Tharga.Cache.csproj +++ b/Tharga.Cache/Tharga.Cache.csproj @@ -13,6 +13,10 @@ https://github.com/Tharga/Cache README.md true + + snupkg true true true From 523f1cf66ee6fa96edcc3de834dc37d92cba7f3b Mon Sep 17 00:00:00 2001 From: Daniel Bohlin Date: Sun, 26 Jul 2026 23:03:18 +0200 Subject: [PATCH 2/2] chore!: bump to 1.0, target net10.0 only, consume tier 3, declare licence Version - MAJOR_MINOR 0.4 -> 1.0. Cache was the last pre-1.0 package series in the toolkit. Frameworks - Tharga.Cache, .Blazor, .Mcp, .MongoDB and .Redis drop net8.0/net9.0 for net10.0 only. Both go out of support on 2026-11-10, and .Blazor had to move regardless since Tharga.Blazor 2.2.3 is net10.0 only. Dependencies - Tharga.MongoDB 2.11.2 -> 2.14.1, Tharga.Blazor 2.2.0 -> 2.2.3, Tharga.Mcp 0.1.6 -> 1.0.0, Tharga.Console 4.1.2 -> 4.2.0. Package metadata - Declared PackageLicenseExpression MIT on all six packages. The repo has an MIT LICENSE file but none of them ever said so, and every push logged "License missing". - Removed from all six projects. CI sets the version at build time, so the value here never reached the package - it only misled anyone reading the file, and it read 1.0.0 while the series shipped 0.4.x. - NU5048 added to NoWarn; PackageIconUrl is deliberate. CI - Version computed before the build and passed as -p:Version, so the assembly and the package agree. Previously only -p:PackageVersion was passed at pack time, leaving AssemblyVersion at 1.0.0.0 in every shipped assembly. The two conditional Pack steps collapse into one covering all six packages. - Guarded the version tag lookup with `|| true`. grep exits 1 when no tag matches the series - which is exactly what starting the new 1.0 series does - and the step would die under `bash -eo pipefail`. - A failed nuget push now fails the release; the loop ended in `|| true`. - SDK install narrowed to 10.0.x. Solution - Removed solution items for azure-pipelines.yml and buildnumber.yml, which no longer exist; added the workflow and LICENSE. Tests: 478 pass. FetchDataThrottleTests.ManyParallelCallsAreQueuedForDifferentTypes is timing-bounded (asserts 500-1200ms) and flaky - it fails intermittently on unmodified master too. --- .github/workflows/build.yml | 134 ++++++++++-------- .../Tharga.Cache.Console.csproj | 2 +- .../Tharga.Cache.Blazor.csproj | 14 +- Tharga.Cache.File/Tharga.Cache.File.csproj | 10 +- Tharga.Cache.Mcp/Tharga.Cache.Mcp.csproj | 14 +- .../Tharga.Cache.MongoDB.csproj | 14 +- Tharga.Cache.Redis/Tharga.Cache.Redis.csproj | 12 +- Tharga.Cache.sln | 3 +- Tharga.Cache/Tharga.Cache.csproj | 12 +- 9 files changed, 132 insertions(+), 83 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index c3f81e7..d8a32cd 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -7,7 +7,7 @@ on: branches: [master] env: - MAJOR_MINOR: '0.4' + MAJOR_MINOR: '1.0' permissions: contents: write @@ -28,42 +28,17 @@ jobs: - name: Setup .NET uses: actions/setup-dotnet@v4 with: - dotnet-version: | - 8.0.x - 9.0.x - 10.0.x - - - name: Restore - run: dotnet restore - - - name: Build - run: dotnet build -c Release --no-restore 2>&1 | tee build.log - - - name: Check warnings - run: | - WARNING_COUNT=$(grep -c " warning " build.log || true) - echo "Build warnings: $WARNING_COUNT" - if [ "$WARNING_COUNT" -gt 10 ]; then - echo "::error::Build has $WARNING_COUNT warnings (threshold: 10)" - exit 1 - fi - - - name: Test with coverage - # Skip Integration (needs Mongo/Redis) and TimeCritical (wall-clock asserts) tests on shared CI runners. - run: dotnet test -c Release --no-build --verbosity normal --filter "(Category!=Integration)&(Category!=TimeCritical)" --collect:"XPlat Code Coverage" --results-directory ./coverage - - - name: Upload coverage to Codecov - uses: codecov/codecov-action@v5 - with: - directory: ./coverage - fail_ci_if_error: false - token: ${{ secrets.CODECOV_TOKEN }} + dotnet-version: 10.0.x + # Version is computed BEFORE the build so it can be passed as -p:Version. + # Passing it only to `dotnet pack` sets PackageVersion alone, leaving + # AssemblyVersion and FileVersion at their default 1.0.0.0 inside the + # shipped assembly. - name: Compute version id: version run: | LATEST_TAG=$(git tag -l "${MAJOR_MINOR}.*" --sort=-v:refname \ - | grep -E "^${MAJOR_MINOR}\.[0-9]+$" \ + | { grep -E "^${MAJOR_MINOR}\.[0-9]+$" || true; } \ | head -1) if [ -z "$LATEST_TAG" ]; then @@ -98,25 +73,56 @@ jobs: echo "version=$PRE_VERSION" >> "$GITHUB_OUTPUT" echo "Computed pre-release version: $PRE_VERSION" - - name: Pack (stable — push to master) - if: github.ref == 'refs/heads/master' && github.event_name == 'push' + # Pull requests build the pre-release version, pushes to master the + # stable one. One value drives build and pack so the assembly and the + # package can never disagree. + - name: Resolve build version + id: buildversion + shell: bash run: | - dotnet pack Tharga.Cache/Tharga.Cache.csproj -c Release --no-build -o ./artifacts -p:PackageVersion=${{ steps.version.outputs.version }} - dotnet pack Tharga.Cache.Redis/Tharga.Cache.Redis.csproj -c Release --no-build -o ./artifacts -p:PackageVersion=${{ steps.version.outputs.version }} - dotnet pack Tharga.Cache.MongoDB/Tharga.Cache.MongoDB.csproj -c Release --no-build -o ./artifacts -p:PackageVersion=${{ steps.version.outputs.version }} - dotnet pack Tharga.Cache.File/Tharga.Cache.File.csproj -c Release --no-build -o ./artifacts -p:PackageVersion=${{ steps.version.outputs.version }} - dotnet pack Tharga.Cache.Blazor/Tharga.Cache.Blazor.csproj -c Release --no-build -o ./artifacts -p:PackageVersion=${{ steps.version.outputs.version }} - dotnet pack Tharga.Cache.Mcp/Tharga.Cache.Mcp.csproj -c Release --no-build -o ./artifacts -p:PackageVersion=${{ steps.version.outputs.version }} - - - name: Pack (pre-release — pull request) - if: github.event_name == 'pull_request' + if [ "${{ github.event_name }}" = "pull_request" ]; then + VERSION="${{ steps.preversion.outputs.version }}" + else + VERSION="${{ steps.version.outputs.version }}" + fi + echo "version=$VERSION" >> "$GITHUB_OUTPUT" + echo "Building as: $VERSION" + + - name: Restore + run: dotnet restore + + - name: Build + run: dotnet build -c Release --no-restore -p:Version=${{ steps.buildversion.outputs.version }} 2>&1 | tee build.log + + - name: Check warnings + run: | + WARNING_COUNT=$(grep -c " warning " build.log || true) + echo "Build warnings: $WARNING_COUNT" + if [ "$WARNING_COUNT" -gt 10 ]; then + echo "::error::Build has $WARNING_COUNT warnings (threshold: 10)" + exit 1 + fi + + - name: Test with coverage + # Skip Integration (needs Mongo/Redis) and TimeCritical (wall-clock asserts) tests on shared CI runners. + run: dotnet test -c Release --no-build --verbosity normal --filter "(Category!=Integration)&(Category!=TimeCritical)" --collect:"XPlat Code Coverage" --results-directory ./coverage + + - name: Upload coverage to Codecov + uses: codecov/codecov-action@v5 + with: + directory: ./coverage + fail_ci_if_error: false + token: ${{ secrets.CODECOV_TOKEN }} + + - name: Pack + shell: bash run: | - dotnet pack Tharga.Cache/Tharga.Cache.csproj -c Release --no-build -o ./artifacts -p:PackageVersion=${{ steps.preversion.outputs.version }} - dotnet pack Tharga.Cache.Redis/Tharga.Cache.Redis.csproj -c Release --no-build -o ./artifacts -p:PackageVersion=${{ steps.preversion.outputs.version }} - dotnet pack Tharga.Cache.MongoDB/Tharga.Cache.MongoDB.csproj -c Release --no-build -o ./artifacts -p:PackageVersion=${{ steps.preversion.outputs.version }} - dotnet pack Tharga.Cache.File/Tharga.Cache.File.csproj -c Release --no-build -o ./artifacts -p:PackageVersion=${{ steps.preversion.outputs.version }} - dotnet pack Tharga.Cache.Blazor/Tharga.Cache.Blazor.csproj -c Release --no-build -o ./artifacts -p:PackageVersion=${{ steps.preversion.outputs.version }} - dotnet pack Tharga.Cache.Mcp/Tharga.Cache.Mcp.csproj -c Release --no-build -o ./artifacts -p:PackageVersion=${{ steps.preversion.outputs.version }} + dotnet pack Tharga.Cache/Tharga.Cache.csproj -c Release --no-build -o ./artifacts -p:Version=${{ steps.buildversion.outputs.version }} + dotnet pack Tharga.Cache.Redis/Tharga.Cache.Redis.csproj -c Release --no-build -o ./artifacts -p:Version=${{ steps.buildversion.outputs.version }} + dotnet pack Tharga.Cache.MongoDB/Tharga.Cache.MongoDB.csproj -c Release --no-build -o ./artifacts -p:Version=${{ steps.buildversion.outputs.version }} + dotnet pack Tharga.Cache.File/Tharga.Cache.File.csproj -c Release --no-build -o ./artifacts -p:Version=${{ steps.buildversion.outputs.version }} + dotnet pack Tharga.Cache.Blazor/Tharga.Cache.Blazor.csproj -c Release --no-build -o ./artifacts -p:Version=${{ steps.buildversion.outputs.version }} + dotnet pack Tharga.Cache.Mcp/Tharga.Cache.Mcp.csproj -c Release --no-build -o ./artifacts -p:Version=${{ steps.buildversion.outputs.version }} - name: Upload artifacts uses: actions/upload-artifact@v4 @@ -138,10 +144,7 @@ jobs: - name: Setup .NET uses: actions/setup-dotnet@v4 with: - dotnet-version: | - 8.0.x - 9.0.x - 10.0.x + dotnet-version: 10.0.x - name: Build for CodeQL run: dotnet build -c Release @@ -175,7 +178,7 @@ jobs: id: version run: | LATEST_TAG=$(git tag -l "${MAJOR_MINOR}.*" --sort=-v:refname \ - | grep -E "^${MAJOR_MINOR}\.[0-9]+$" \ + | { grep -E "^${MAJOR_MINOR}\.[0-9]+$" || true; } \ | head -1) if [ -z "$LATEST_TAG" ]; then @@ -191,9 +194,15 @@ jobs: - name: Push to NuGet run: | + # Only *.nupkg is globbed. Each matching package's sibling .snupkg is + # uploaded automatically by dotnet nuget push, so symbols must NOT be + # pushed explicitly or nuget.org sees a duplicate. + ls -l ./artifacts/ for pkg in ./artifacts/*.nupkg; do echo "Pushing $pkg..." - dotnet nuget push "$pkg" --api-key ${{ secrets.NUGET_API_KEY }} --source https://api.nuget.org/v3/index.json --skip-duplicate || true + # --skip-duplicate already makes a re-run of an existing version a + # success, so a failure here is a real failure and must fail the job. + dotnet nuget push "$pkg" --api-key ${{ secrets.NUGET_API_KEY }} --source https://api.nuget.org/v3/index.json --skip-duplicate done - name: Create GitHub Release @@ -249,7 +258,7 @@ jobs: id: version run: | LATEST_TAG=$(git tag -l "${MAJOR_MINOR}.*" --sort=-v:refname \ - | grep -E "^${MAJOR_MINOR}\.[0-9]+$" \ + | { grep -E "^${MAJOR_MINOR}\.[0-9]+$" || true; } \ | head -1) if [ -z "$LATEST_TAG" ]; then @@ -274,9 +283,15 @@ jobs: - name: Push to NuGet run: | + # Only *.nupkg is globbed. Each matching package's sibling .snupkg is + # uploaded automatically by dotnet nuget push, so symbols must NOT be + # pushed explicitly or nuget.org sees a duplicate. + ls -l ./artifacts/ for pkg in ./artifacts/*.nupkg; do echo "Pushing $pkg..." - dotnet nuget push "$pkg" --api-key ${{ secrets.NUGET_API_KEY }} --source https://api.nuget.org/v3/index.json --skip-duplicate || true + # --skip-duplicate already makes a re-run of an existing version a + # success, so a failure here is a real failure and must fail the job. + dotnet nuget push "$pkg" --api-key ${{ secrets.NUGET_API_KEY }} --source https://api.nuget.org/v3/index.json --skip-duplicate done - name: Create GitHub Pre-release @@ -300,10 +315,7 @@ jobs: - name: Setup .NET uses: actions/setup-dotnet@v4 with: - dotnet-version: | - 8.0.x - 9.0.x - 10.0.x + dotnet-version: 10.0.x - name: Install DocFX run: dotnet tool install -g docfx diff --git a/Sample/Tharga.Cache.Console/Tharga.Cache.Console.csproj b/Sample/Tharga.Cache.Console/Tharga.Cache.Console.csproj index 88fd6c5..0519e87 100644 --- a/Sample/Tharga.Cache.Console/Tharga.Cache.Console.csproj +++ b/Sample/Tharga.Cache.Console/Tharga.Cache.Console.csproj @@ -7,7 +7,7 @@ - + diff --git a/Tharga.Cache.Blazor/Tharga.Cache.Blazor.csproj b/Tharga.Cache.Blazor/Tharga.Cache.Blazor.csproj index 3c5c359..8179598 100644 --- a/Tharga.Cache.Blazor/Tharga.Cache.Blazor.csproj +++ b/Tharga.Cache.Blazor/Tharga.Cache.Blazor.csproj @@ -1,13 +1,13 @@  - net9.0;net10.0 + net10.0 enable - 1.0.0 Daniel Bohlin Thargelion AB Tharga Cache Blazor Component for manageing the Tharga Cache features in blazor. https://thargelion.net/assets/component-cache.png + MIT True README.md portable @@ -22,7 +22,13 @@ snupkg - 1701;1702;CS1591;CS0809 + + 1701;1702;CS1591;CS0809;NU5048 @@ -31,7 +37,7 @@ - + diff --git a/Tharga.Cache.File/Tharga.Cache.File.csproj b/Tharga.Cache.File/Tharga.Cache.File.csproj index a9b645f..314ee1b 100644 --- a/Tharga.Cache.File/Tharga.Cache.File.csproj +++ b/Tharga.Cache.File/Tharga.Cache.File.csproj @@ -2,12 +2,12 @@ net10.0 enable - 1.0.0 Daniel Bohlin Thargelion AB Tharga Cache File File cache features. https://thargelion.net/assets/component-cache.png + MIT True https://github.com/Tharga/Cache README.md @@ -25,7 +25,13 @@ enable - 1701;1702;CS1591 + + 1701;1702;CS1591;NU5048 diff --git a/Tharga.Cache.Mcp/Tharga.Cache.Mcp.csproj b/Tharga.Cache.Mcp/Tharga.Cache.Mcp.csproj index 71b3d5b..8effc5d 100644 --- a/Tharga.Cache.Mcp/Tharga.Cache.Mcp.csproj +++ b/Tharga.Cache.Mcp/Tharga.Cache.Mcp.csproj @@ -1,14 +1,14 @@  - net8.0;net9.0;net10.0 + net10.0 enable - 1.0.0 Daniel Bohlin Thargelion AB Tharga Cache MCP Exposes Tharga.Cache monitoring data (cache types, items, persistence health, fetch queue) and actions (clear all, clear stale) via MCP (Model Context Protocol). Plugs into Tharga.Mcp. https://thargelion.net/assets/component-cache.png + MIT True https://github.com/Tharga/Cache README.md @@ -26,7 +26,13 @@ - 1701;1702;CS1591;CS0809 + + 1701;1702;CS1591;CS0809;NU5048 @@ -37,7 +43,7 @@ - + all runtime; build; native; contentfiles; analyzers; buildtransitive diff --git a/Tharga.Cache.MongoDB/Tharga.Cache.MongoDB.csproj b/Tharga.Cache.MongoDB/Tharga.Cache.MongoDB.csproj index cc29dcb..52f3d43 100644 --- a/Tharga.Cache.MongoDB/Tharga.Cache.MongoDB.csproj +++ b/Tharga.Cache.MongoDB/Tharga.Cache.MongoDB.csproj @@ -1,13 +1,13 @@  - net8.0;net9.0;net10.0 + net10.0 enable - 1.0.0 Daniel Bohlin Thargelion AB Tharga Cache MongoDB MongoDB cache features. https://thargelion.net/assets/component-cache.png + MIT True https://github.com/Tharga/Cache README.md @@ -25,7 +25,13 @@ enable - 1701;1702;CS1591 + + 1701;1702;CS1591;NU5048 @@ -43,7 +49,7 @@ all runtime; build; native; contentfiles; analyzers; buildtransitive - + diff --git a/Tharga.Cache.Redis/Tharga.Cache.Redis.csproj b/Tharga.Cache.Redis/Tharga.Cache.Redis.csproj index d69689e..f88a938 100644 --- a/Tharga.Cache.Redis/Tharga.Cache.Redis.csproj +++ b/Tharga.Cache.Redis/Tharga.Cache.Redis.csproj @@ -1,14 +1,14 @@  - net8.0;net9.0;net10.0 + net10.0 enable - 1.0.0 Daniel Bohlin Thargelion AB Tharga Cache Redis Redis cache features. https://thargelion.net/assets/component-cache.png + MIT True https://github.com/Tharga/Cache README.md @@ -27,7 +27,13 @@ - 1701;1702;CS1591 + + 1701;1702;CS1591;NU5048 diff --git a/Tharga.Cache.sln b/Tharga.Cache.sln index 74debe2..4e7182f 100644 --- a/Tharga.Cache.sln +++ b/Tharga.Cache.sln @@ -9,7 +9,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Tharga.Cache.Tests", "Tharg EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{B2037503-DDED-46E6-BF80-9E2914A10291}" ProjectSection(SolutionItems) = preProject - azure-pipelines.yml = azure-pipelines.yml + .github\workflows\build.yml = .github\workflows\build.yml + LICENSE = LICENSE README.md = README.md switcher.json = switcher.json EndProjectSection diff --git a/Tharga.Cache/Tharga.Cache.csproj b/Tharga.Cache/Tharga.Cache.csproj index c6054ca..59f110d 100644 --- a/Tharga.Cache/Tharga.Cache.csproj +++ b/Tharga.Cache/Tharga.Cache.csproj @@ -1,14 +1,14 @@  - net8.0;net9.0;net10.0 + net10.0 enable - 1.1.0 Daniel Bohlin Thargelion AB Tharga Cache Memory cache features. https://thargelion.net/assets/component-cache.png + MIT True https://github.com/Tharga/Cache README.md @@ -27,7 +27,13 @@ - 1701;1702;CS1591 + + 1701;1702;CS1591;NU5048