Repository navigation
feat!: target net9.0 and net10.0 with configurable frameworks - #214
Conversation
Library and test projects now read their target frameworks from FirebendTargetFrameworks in Directory.Build.props; the samples use FirebendAppTargetFramework (net10.0). Package versions move to central package management in Directory.Packages.props, with per-framework versions for the Microsoft.Extensions and EF Core packages (9.0.20 on net9.0, 10.0.12 on net10.0) and the other packages updated to their latest stable releases. A repo nuget.config pins restore to nuget.org. CI installs both the 9.0 and 10.0 SDKs, and the checkout and setup-dotnet actions move to v4. Hosted service tests now await ExecuteTask, since BackgroundService.StartAsync no longer runs ExecuteAsync inline on .NET 10. BREAKING CHANGE: packages now target only net9.0 and net10.0. Each Jobba package ships lib/net9.0 and lib/net10.0, and net10.0 consumers now get Microsoft.Extensions.* and Microsoft.EntityFrameworkCore.* 10.0.x dependencies (9.0.20 on net9.0). Minimum dependency versions rise to MassTransit 8.5.11, MongoDB.Driver 3.12.0 and Cronos 0.13.0. On .NET 10, a failing IJobbaReadyGate no longer makes JobbaHostedService.StartAsync throw; the failure surfaces from the background task instead. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01JMzvDp6hZ4dnMSGobxdo98
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01JMzvDp6hZ4dnMSGobxdo98
FluentAssertions 8 requires a commercial license. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01JMzvDp6hZ4dnMSGobxdo98
Replaces the deprecated PackageLicenseUrl and PackageIconUrl (NU5125, NU5048) with PackageLicenseExpression and an embedded nuget-image.png, packed from Directory.Build.props for every project that sets PackageIcon. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01JMzvDp6hZ4dnMSGobxdo98
global.json pins SDK 10.0.401 with rollForward latestPatch, so local builds and CI run the same analyzer rules and a new SDK feature band can no longer break dotnet format without a code change. CI reads global.json through setup-dotnet and still installs the 9.0 SDK for the net9.0 test runtime. The release workflow now sets up .NET before installing Versionize, so the dotnet tool install runs on the pinned SDK. Dependabot opens monthly dotnet-sdk updates for global.json. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01JMzvDp6hZ4dnMSGobxdo98
mcarey1590
left a comment
There was a problem hiding this comment.
Reviewed the full diff. Nothing blocking; leaning approve. CI green; integration tests not run (need external services).
Medium
- The hosted-service change follows the .NET 10 runtime, not the library TFM: on any .NET 10 runtime a ready-gate failure no longer throws from
StartAsyncand instead goes through the host'sBackgroundServiceExceptionBehavior. net9.0 consumers running on .NET 10 are affected too. The BREAKING CHANGE footer ties it to ".NET 10" only, so please make that explicit in the notes. The updatedShould_Throw_When_Ready_Gate_Failspasses on both runtimes but no longer pins either behavior. - The PR notes one net10.0 failure in a full-solution run that didn't reproduce in 13 reruns. A flaky test in the release workflow would block a publish; worth identifying which one.
Low
JobRegistration.cs:93-102/JobbaCoreOptions.cs:26-31:fieldkeyword refactor.JobRegistrationis a persisted entity, so this is the only change that could affect behavior beyond build config. EF should find the compiler-generated backing field by convention, but I didn't see a test of EF 9.0.20 on net9.0 with it.global.jsonpins10.0.401withrollForward: latestPatch; anyone on another feature band can't build.latestFeaturewould be friendlier.- Per-TFM
PackageVersionblocks may confuse Dependabot; watch the first monthly PRs. - Nit:
dotnet-ef10.0.12 vs EF 9.0.20 packages on net9.0.
Ordering: Jobba depends only on LitRedis.Core (pinned 5.0.0). Better to merge after lit-redis#151 releases, otherwise Jobba.Redis needs a second major bump later.
Adds a Building from source section covering global.json and the FirebendTargetFrameworks and FirebendAppTargetFramework properties. Dependabot now ignores major updates to the framework-aligned Microsoft packages, which are versioned per target framework in Directory.Packages.props. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01JMzvDp6hZ4dnMSGobxdo98
Assert that StartAsync throws the gate's exception before .NET 10, and that from .NET 10 StartAsync completes while ExecuteTask faults with it, instead of accepting either path. Guard that the Microsoft.Extensions.Hosting.Abstractions major version matches the runtime so the branch reflects the loaded BackgroundService. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01JMzvDp6hZ4dnMSGobxdo98
TimeZoneId moved to a field-backed property, which changes the backing field EF discovers. Pin that the TimeZoneId column is still written and read, that the UTC default survives persistence, and that re-registering a job updates the stored zone and resets the cached TimeZoneInfo. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01JMzvDp6hZ4dnMSGobxdo98
The pub/sub tests started the receiver hosted service a second time after harness.Start() had already started it, then published immediately. From .NET 10 BackgroundService.StartAsync returns before ExecuteAsync connects the receive endpoints, so the publish raced the endpoint and the message was dropped, failing intermittently under load. Await the service's ready gate, which completes once every endpoint reports ready, and drop the duplicate start that tried to connect the same endpoint twice. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01JMzvDp6hZ4dnMSGobxdo98
|
Responses to the review: Medium
Low
Ordering: agreed. I'll hold this until lit-redis#151 releases 6.0.0, then bump |
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01UvmzsCHKfHVMozvywp42FU
mcarey1590
left a comment
There was a problem hiding this comment.
Re-checked after latest commits. All review items addressed: ready-gate behavior documented in PR description and pinned per runtime in tests, flaky MassTransit pub/sub tests root-caused and fixed (25/25 full runs), JobRegistration field-keyword EF mapping verified plus Sqlite round-trip tests, latestPatch pin rationale + README, Dependabot ignore, dotnet-ef verified, LitRedis.Core 6.0.0 bump (published on NuGet) so Jobba.Redis takes one major. CI green on head. Integration tests still unrun (need external services).
Summary
FirebendTargetFrameworksinDirectory.Build.props(currentlynet9.0;net10.0). Samples and other runnable apps useFirebendAppTargetFramework(net10.0). Adding .NET 11 later means editing that list and adding onenet11.0block toDirectory.Packages.props.Directory.Packages.props. Microsoft framework packages are versioned per framework: 9.0.x for net9.0 and 10.0.x for net10.0. Other packages are updated to their latest stable versions.nuget.configrestricts restore to nuget.org.global.jsonpins SDK 10.0.401 withrollForward: latestPatch, so local builds and CI run the same analyzer rules. CI reads it throughactions/setup-dotnet@v4(global-json-file) and also installs the 9.0 SDK for the net9.0 test runtime. CI usesactions/checkout@v4.dotnet-sdkupdates forglobal.json.PackageLicenseExpression(MIT) instead of the deprecatedPackageIconUrlandPackageLicenseUrl(NU5048, NU5125).feat!:with aBREAKING CHANGE:footer, so Versionize will release a new major version.jobba specifics
Microsoft.Extensions.Hostingversion the app runs with (normally the runtime's), not the TFM of the Jobba package, so net9.0 consumers running on .NET 10 are affected too. With .NET 10 hosting,BackgroundService.StartAsyncruns all ofExecuteAsyncas a task, so a failingIJobbaReadyGateno longer makesJobbaHostedService.StartAsyncthrow.BackgroundServiceExceptionBehavior.StopHost, it stops gracefully andRunAsyncreturns without rethrowing, so the exit code is 0 unless the app sets one.Ignore, the host keeps running with Jobba uninitialized, and the only sign is the error log.Should_Throw_When_Ready_Gate_Failsnow asserts the exact behavior for each hosting version.fieldkeyword.JobRegistration.TimeZoneInfokeeps its backing field, with the warning suppressed on that line, because the fix would add a setter to a persisted entity.Test plan
dotnet build -c Release: 0 warnings, 0 errors (SDK 10.0.401)dotnet format --verify-no-changespassesMassTransit_Job_Event_Publisher_Should_Pub_Sub_*tests were flaky on .NET 10. They started the receiver service a second time and published before its receive endpoints were connected, which .NET 10'sStartAsyncno longer waits for. They now wait on the service's ready gate. 25 full-solution runs and 40 loaded runs passed after the fix.lib/net9.0andlib/net10.0, the embedded icon, and the MIT license expressionRelease order: this references LitRedis.Core 5.0.0. Bump it to 6.0.0 in a follow-up once lit-redis is released.
🤖 Generated with Claude Code
https://claude.ai/code/session_01JMzvDp6hZ4dnMSGobxdo98