EasyMessages v1.0.0 Release Design

Date: 2026-05-10 Status: Approved Author: RecurPixel


Context

EasyMessages has been in beta since January 2026 as two packages:

  • RecurPixel.EasyMessages (Core) — 500 NuGet downloads
  • RecurPixel.EasyMessages.AspNetCore — 80 NuGet downloads

The 6:1 download ratio confirmed that the Core package is the real product. Beta feedback showed no meaningful demand for the AspNetCore-specific integration. The Core package already covers web developer needs via .ToJson() and direct StatusCode() returns.

Decision: Release Core as v1.0.0 (stable), deprecate AspNetCore as v0.1.0 (final), move .Log(ILogger) into Core since ILogger is cross-platform and benefits all users.


Packages

Package Version Action
RecurPixel.EasyMessages 1.0.0 Stable release
RecurPixel.EasyMessages.AspNetCore 0.1.0 Final release, deprecated

Section 1: Code Changes

Core (RecurPixel.EasyMessages)

1. Move .Log(ILogger) into Core

  • Create src/RecurPixel.EasyMessages/Extensions/MessageExtensions.Logging.cs
  • Copy the implementation from src/RecurPixel.EasyMessages.AspNetCore/Extensions/MessageLoggingExtensions.cs
  • The method signature: public static Message Log(this Message message, ILogger logger) — returns Message so it stays chainable
  • Log level mapping: Error/Critical → LogError, Warning → LogWarning, Success/Info → LogInformation
  • Add Microsoft.Extensions.Logging.Abstractions package reference to Core .csproj (lightweight, cross-platform, standard in all .NET apps)

2. Version bump

  • src/RecurPixel.EasyMessages/RecurPixel.EasyMessages.csproj: Version → 1.0.0
  • Remove -beta.1 suffix everywhere it appears in Core .csproj metadata

3. Core README rewrite

  • Remove all mentions of RecurPixel.EasyMessages.AspNetCore
  • Remove the two-package table and dual installation instructions
  • Rewrite as a single-package story
  • Web API usage section: replace .ToApiResponse() with return StatusCode(msg.HttpStatusCode, msg.ToJsonObject())
  • Add .Log(ILogger) to the feature list and examples
  • Update version references: 0.1.0-beta.* → 1.0.0

4. CHANGELOG

  • Add [1.0.0] - 2026-05-10 entry: stable release, .Log(ILogger) moved to Core, AspNetCore deprecated
  • Document migration path for AspNetCore users

AspNetCore (RecurPixel.EasyMessages.AspNetCore)

1. Remove .Log(ILogger) to avoid duplication

  • Delete Extensions/MessageLoggingExtensions.cs (now in Core, which AspNetCore already references)

2. Version bump

  • Version → 0.1.0 (drop -beta.1)

3. Add deprecation metadata to .csproj

<Deprecated>true</Deprecated>
<DeprecatedMessage>
  This package is deprecated. Use RecurPixel.EasyMessages (Core) instead.
  Migration: replace .ToApiResponse() with StatusCode(msg.HttpStatusCode, msg.ToJsonObject()).
  See: https://github.com/RecurPixel/RecurPixel.EasyMessages
</DeprecatedMessage>

4. AspNetCore README

  • Add a prominent deprecation banner at the top
  • Include a concise migration guide:
    • dotnet remove package RecurPixel.EasyMessages.AspNetCore
    • dotnet add package RecurPixel.EasyMessages --version 1.0.0
    • Replace .ToApiResponse() → StatusCode(msg.HttpStatusCode, msg.ToJsonObject())
    • Replace .ToMinimalApiResult() → Results.Json(msg.ToJsonObject(), statusCode: msg.HttpStatusCode)
    • Remove builder.Services.AddEasyMessages() from Program.cs

Section 2: Testing

Existing suite

  • Run all 237 tests across net8.0, net9.0, net10.0
  • Build configuration: Release
  • Warnings as errors: /warnaserror — zero warnings allowed for 1.0.0

New tests for .Log(ILogger)

Location: tests/RecurPixel.EasyMessages.Tests/

Cover:

  • Error message type → LogError called
  • Warning message type → LogWarning called
  • Success message type → LogInformation called
  • Info message type → LogInformation called
  • Return value is the same Message instance (chaining works)
  • .Log(logger).ToJson() chain compiles and executes correctly

Use Microsoft.Extensions.Logging.Abstractions’s built-in NullLogger and FakeLogger — no mocking frameworks needed.

Package smoke test

  • dotnet pack -c Release both packages locally
  • Install Core from local source into a fresh dotnet new console project
  • Install Core from local source into a fresh dotnet new webapi project
  • Verify Msg.Auth.LoginFailed().Log(logger).ToJson() compiles and runs in both

Section 3: Playground

Location: samples/EasyMessages.Playground/

Promote and expand the existing ConsoleSample into a proper playground:

  • Target net8.0, project reference to Core
  • Sections that demonstrate each feature group:
    • All message categories (Msg.Auth, Msg.Crud, Msg.Validation, Msg.System, etc.)
    • All output formatters (ToJson(), ToXml(), ToConsole(), ToPlainText())
    • .Log(ILogger) chaining with a real ConsoleLogger
    • Parameter substitution via .WithParams()
    • Custom messages via FileMessageStore
    • Interceptors
    • Metadata and correlation ID
  • Self-contained: running dotnet run from the folder produces a clear, readable output of all features

Section 4: CI/CD Pipeline

.github/workflows/ci.yml

Triggers: push and pull_request to main

Steps:

  1. Checkout
  2. Setup .NET 10.0.x
  3. dotnet restore
  4. dotnet build --configuration Release --no-restore
  5. dotnet test --configuration Release --no-build --verbosity normal
  6. dotnet pack --configuration Release --no-restore --output ./nupkgs
  7. Verify at least 1 .nupkg exists (Core)

.github/workflows/publish-nuget.yml

Triggers: GitHub Release published

Steps:

  1. Checkout, setup .NET 10.0.x
  2. Restore → Build Release → Test
  3. Pack both packages to ./nupkgs
  4. Tier 0: Push RecurPixel.EasyMessages (Core, no deps)
  5. Wait 120s for NuGet indexing
  6. Tier 1: Push RecurPixel.EasyMessages.AspNetCore (depends on Core)
  7. Upload .nupkg and .snupkg as GitHub Release assets
  8. Print release summary

.github/workflows/docs.yml

Triggers: push to main on docs/** changes, and workflow_dispatch

Same pattern as RecurPixel.Notify — Jekyll build + deploy to GitHub Pages.


Section 5: Docker Test Suite

Dockerfile.test

Mirrors the CI environment locally (Ubuntu + .NET SDK latest):

FROM mcr.microsoft.com/dotnet/sdk:latest
WORKDIR /workspace
COPY . .
RUN dotnet restore
RUN dotnet build --configuration Release --no-restore
RUN dotnet test --configuration Release --no-build --verbosity normal
RUN dotnet pack --configuration Release --no-restore --output ./nupkgs
RUN verify exactly 1 .nupkg (Core only — AspNetCore packed separately as one-off)
CMD ["/bin/bash"]

test-workflow.sh

Shell script to build and run Dockerfile.test locally before pushing:

  • Checks Docker is installed
  • Builds the image: docker build -f Dockerfile.test -t easymessages-test:latest .
  • Prints next steps on success (review output → commit → push → create GitHub release)

Migration Guide for AspNetCore Users

For the 80 existing AspNetCore beta users, the migration is minimal:

dotnet remove package RecurPixel.EasyMessages.AspNetCore
dotnet add package RecurPixel.EasyMessages --version 1.0.0
Before (AspNetCore) After (Core only)
Msg.Auth.LoginFailed().ToApiResponse() StatusCode(msg.HttpStatusCode, msg.ToJsonObject())
Msg.Crud.Created("User").ToMinimalApiResult() Results.Json(msg.ToJsonObject(), statusCode: msg.HttpStatusCode)
builder.Services.AddEasyMessages() Remove — not needed
.Log(_logger) Same — .Log() is now in Core

Success Criteria

The release is complete when:

  • All 237+ tests pass on net8.0, net9.0, net10.0 with zero warnings
  • .Log(ILogger) new tests pass
  • Package smoke test succeeds in both console and web projects
  • Playground runs cleanly with dotnet run
  • Dockerfile.test builds and passes locally via test-workflow.sh
  • CI workflow is green on a push to main
  • Core v1.0.0 and AspNetCore v0.1.0 published to NuGet
  • AspNetCore shows as deprecated on NuGet
  • Core README reflects single-package story
  • GitHub Release created with packages attached