diff --git a/.github/RELEASE_TEMPLATE.md b/.github/RELEASE_TEMPLATE.md new file mode 100644 index 00000000..008f37c2 --- /dev/null +++ b/.github/RELEASE_TEMPLATE.md @@ -0,0 +1,32 @@ + + +## Kalicz.StrongTypes + +- + +## Kalicz.StrongTypes.EfCore + +- + +## Kalicz.StrongTypes.FsCheck + +- + +## Breaking changes + +- + +## Upgrade notes + +- diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index f3be3c3b..ec8939ad 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -7,6 +7,8 @@ on: pull_request: branches: - main + release: + types: [published] permissions: contents: read @@ -48,36 +50,54 @@ jobs: **/TestResults/**/*.trx retention-days: 5 - - name: Pack - if: github.ref == 'refs/heads/main' && github.event_name == 'push' - run: | - dotnet pack ./src/StrongTypes/StrongTypes.csproj -c $config -o out - dotnet pack ./src/StrongTypes.EfCore/StrongTypes.EfCore.csproj -c $config -o out - - - name: Upload NuGet package - if: github.ref == 'refs/heads/main' && github.event_name == 'push' - uses: actions/upload-artifact@v7 - with: - name: nuget-package - path: out/*.nupkg - retention-days: 1 - publish: needs: build - if: github.ref == 'refs/heads/main' && github.event_name == 'push' + # Gate on main: a Release drafted through the UI carries the selected + # branch in target_commitish. Only releases targeted at main publish. + if: github.event_name == 'release' && github.event.release.target_commitish == 'main' runs-on: ubuntu-latest environment: Nuget.org + env: + config: 'Release' + DOTNET_NOLOGO: true + DOTNET_CLI_TELEMETRY_OPTOUT: true + steps: - - name: Download NuGet package - uses: actions/download-artifact@v8 - with: - name: nuget-package + - name: Checkout + uses: actions/checkout@v6 - name: Setup .NET 10 uses: actions/setup-dotnet@v5 with: dotnet-version: 10.0.x + - name: Parse version from tag + id: version + run: | + TAG="${GITHUB_REF_NAME}" + echo "version=${TAG#v}" >> "$GITHUB_OUTPUT" + + # GeneratePackageOnBuild=true in the csproj files means `dotnet build` + # produces the nupkg as a side-effect; no separate `dotnet pack` step + # needed. -p:Version cascades into referenced projects (EfCore's + # ProjectReference to core), so EfCore's nuspec pins its core + # dependency to the same version. + # Build the whole solution; non-publishable projects (tests, internal + # source generators, analyzers) set IsPackable=false so they produce no + # nupkg. GeneratePackageOnBuild=true on publishable csprojs means the + # build itself emits .nupkg files into PackageOutputPath. New publishable + # packages are picked up automatically by setting the same two properties. + - name: Build and pack + env: + NOTES: ${{ github.event.release.body }} + VERSION: ${{ steps.version.outputs.version }} + run: | + dotnet build StrongTypes.slnx \ + -c $config \ + -p:Version="$VERSION" \ + -p:PackageReleaseNotes="$NOTES" \ + -p:PackageOutputPath="$PWD/out" + - name: Publish packages - run: dotnet nuget push ./*.nupkg --skip-duplicate --source nuget.org --api-key ${{secrets.NUGET_TOKEN}} + run: dotnet nuget push ./out/*.nupkg --source nuget.org --api-key ${{ secrets.NUGET_TOKEN }} diff --git a/StrongTypes.slnx b/StrongTypes.slnx index c2558381..53dc544e 100644 --- a/StrongTypes.slnx +++ b/StrongTypes.slnx @@ -6,6 +6,9 @@ + + + diff --git a/src/StrongTypes.EfCore/StrongTypes.EfCore.csproj b/src/StrongTypes.EfCore/StrongTypes.EfCore.csproj index dbd5ba08..cf8c05ea 100644 --- a/src/StrongTypes.EfCore/StrongTypes.EfCore.csproj +++ b/src/StrongTypes.EfCore/StrongTypes.EfCore.csproj @@ -7,9 +7,7 @@ true CS1591 - 0.3.0 - 0.3.0 - 0.3.0 + 0.0.0-dev Kalicz.StrongTypes.EfCore KaliCZ Copyright © 2026 KaliCZ @@ -21,7 +19,6 @@ git https://github.com/KaliCZ/StrongTypes.git readme.md - 0.3.0: Initial release. Ships NonEmptyString and numeric-wrapper value converters. Single-call configuration via optionsBuilder.UseStrongTypes(). true true diff --git a/src/StrongTypes.Tests/Generators.cs b/src/StrongTypes.FsCheck/Generators.cs similarity index 93% rename from src/StrongTypes.Tests/Generators.cs rename to src/StrongTypes.FsCheck/Generators.cs index f28f2a47..d4a2381e 100644 --- a/src/StrongTypes.Tests/Generators.cs +++ b/src/StrongTypes.FsCheck/Generators.cs @@ -1,16 +1,12 @@ -#nullable enable - -using System.Collections.Generic; using FsCheck; using FsCheck.Fluent; -namespace StrongTypes.Tests; +namespace StrongTypes.FsCheck; /// -/// Shared FsCheck arbitraries for the test project. Reference via +/// Shared FsCheck arbitraries for Kalicz.StrongTypes. Reference via /// [Properties(Arbitrary = new[] { typeof(Generators) })] -/// on a test class. Add new arbitraries here rather than creating -/// per-feature generator classes. +/// on a test class. /// public static class Generators { @@ -80,7 +76,7 @@ public static class Generators /// /// with ~20% chance of . /// FsCheck's default string generator never produces null, so - /// the None branch has to be injected explicitly via . + /// the None branch has to be injected explicitly via Gen.Frequency. /// Empty and whitespace strings are kept as valid Some values — use /// when you want the non-empty invariant. /// diff --git a/src/StrongTypes.FsCheck/StrongTypes.FsCheck.csproj b/src/StrongTypes.FsCheck/StrongTypes.FsCheck.csproj new file mode 100644 index 00000000..a2a4ad84 --- /dev/null +++ b/src/StrongTypes.FsCheck/StrongTypes.FsCheck.csproj @@ -0,0 +1,34 @@ + + + net10.0 + 14.0 + enable + enable + true + CS1591 + + 0.0.0-dev + Kalicz.StrongTypes.FsCheck + KaliCZ + Copyright © 2026 KaliCZ + FsCheck arbitraries for Kalicz.StrongTypes. Drop-in property-test support for NonEmptyString, Positive<T>, NonNegative<T>, Negative<T>, NonPositive<T>, Maybe<T>, and NonEmptyEnumerable<T> via a single [Properties(Arbitrary = new[] { typeof(Generators) })] attribute. + StrongTypes, FsCheck, PropertyTesting, Arbitrary, Generators + MIT + false + https://github.com/KaliCZ/StrongTypes + git + https://github.com/KaliCZ/StrongTypes.git + readme.md + true + true + + + + + + + + + + + diff --git a/src/StrongTypes.FsCheck/readme.md b/src/StrongTypes.FsCheck/readme.md new file mode 100644 index 00000000..6cbed8e7 --- /dev/null +++ b/src/StrongTypes.FsCheck/readme.md @@ -0,0 +1,49 @@ +# Kalicz.StrongTypes.FsCheck + +FsCheck arbitraries for [Kalicz.StrongTypes](https://www.nuget.org/packages/Kalicz.StrongTypes). +Lets you write property tests against code that takes or returns `NonEmptyString`, +`Positive`, `NonNegative`, `Negative`, `NonPositive`, `Maybe`, and +`NonEmptyEnumerable` without hand-rolling generators that re-derive each type's +invariants. + +## Install + +```powershell +dotnet add package Kalicz.StrongTypes.FsCheck +``` + +## Register + +Register everything with one attribute on your test class: + +```csharp +using FsCheck.Xunit; +using StrongTypes.FsCheck; + +[Properties(Arbitrary = new[] { typeof(Generators) })] +public class MyTests +{ + [Property] + public void NonEmptyString_round_trips_through_json(NonEmptyString value) + { + // value is guaranteed non-null, non-empty, non-whitespace + } + + [Property] + public void Positive_stays_positive(Positive value) + { + Assert.True(value.Value > 0); + } +} +``` + +## What ships + +- `NonEmptyString` — filtered to non-null, non-whitespace values +- `NullableNonEmptyString` — ~10% null injection +- `Positive`, `Negative`, `NonNegative`, `NonPositive` +- `Maybe`, `Maybe`, `Maybe`, `Maybe>` — + ~20% `None` injection +- `NonEmptyEnumerable` + +Version matches the core `Kalicz.StrongTypes` package you install alongside it. diff --git a/src/StrongTypes.Tests/GlobalUsings.cs b/src/StrongTypes.Tests/GlobalUsings.cs new file mode 100644 index 00000000..1456e4d5 --- /dev/null +++ b/src/StrongTypes.Tests/GlobalUsings.cs @@ -0,0 +1 @@ +global using StrongTypes.FsCheck; diff --git a/src/StrongTypes.Tests/StrongTypes.Tests.csproj b/src/StrongTypes.Tests/StrongTypes.Tests.csproj index b917b0c6..2eeaedb5 100644 --- a/src/StrongTypes.Tests/StrongTypes.Tests.csproj +++ b/src/StrongTypes.Tests/StrongTypes.Tests.csproj @@ -15,5 +15,6 @@ + diff --git a/src/StrongTypes/StrongTypes.csproj b/src/StrongTypes/StrongTypes.csproj index ac699ddc..382ff526 100644 --- a/src/StrongTypes/StrongTypes.csproj +++ b/src/StrongTypes/StrongTypes.csproj @@ -2,9 +2,7 @@ true CS1591 - 0.3.0 - 0.3.0 - 0.3.0 + 0.0.0-dev Kalicz.StrongTypes A C# library that reduces boilerplate and prevents bugs through stronger typing. Continuation of FuncSharp. KaliCZ @@ -13,7 +11,6 @@ https://github.com/KaliCZ/StrongTypes MIT false - 0.3.0: Generic numeric types: Positive<T>, NonNegative<T>, Negative<T>, NonPositive<T>. Added a full E2E capability for these types and NonEmptyString - API JSON serialization and EF Core converters in a separate Kalicz.StrongTypes.EfCore. git https://github.com/KaliCZ/StrongTypes true