Skip to content

[Next] Strengthen public API governance, nullability and regression protection #215

Description

@rodri-oliveira-dev

Pain / problem

FluentMap 3.x now exposes a substantially larger public surface across core mapping, isolated runtimes, DI, analyzers, generators, streaming, multi-mapping and generated materialization.

The repository already has package validation, tests, Sonar, CodeQL and BenchmarkDotNet, but several long-term maintenance protections are still missing:

  • public API changes are not reviewed against an explicit checked-in API snapshot;
  • nullable reference type annotations are not enabled consistently on the public libraries;
  • compatibility validation is focused on the currently supported/pinned dependency matrix and does not provide early warning for upcoming dependency changes;
  • benchmarks exist but performance drift is not tracked as a first-class regression signal.

Goal

Make public API evolution, nullability, forward-compatibility signals and performance regressions explicit and reviewable without introducing flaky required gates.

Branch and delivery workflow

This is the final implementation workstream of roadmap #216 and continues on the shared branch roadmap/216-next-3x.

Scope / implementation requirements

1. Add explicit public API governance

Introduce checked-in public API baselines for every shipped library package.

A PublicAPI.Shipped.txt / PublicAPI.Unshipped.txt model using Roslyn PublicApiAnalyzers is acceptable and preferred when it fits the existing analyzer/tooling stack. An equivalent deterministic API-snapshot mechanism is acceptable if it provides the same review guarantees.

Cover at least:

  • Dapper.FluentMap;
  • Dapper.FluentMap.Dommel;
  • FluentMap.DependencyInjection;
  • public analyzer/generator package API where applicable.

CI must fail when a public API changes without an intentional baseline update.

Package validation remains enabled; API snapshots complement it rather than replace it.

2. Enable and correct nullable reference type annotations

Enable nullable analysis for maintained source projects in a controlled way.

Requirements:

  • public contracts must accurately distinguish nullable from non-nullable values;
  • avoid widespread ! suppression as a substitute for modeling the contract;
  • preserve binary compatibility;
  • avoid unnecessary source-breaking annotation changes where the API cannot safely make a stronger promise;
  • annotate asynchronous/streaming/multi-mapping null-child scenarios consistently;
  • update XML documentation where null behavior is part of the contract.

If enabling nullable globally reveals too much debt for one safe change, introduce project-level staged enforcement, but the final public shipped API must have a deliberate nullable contract.

3. Add compatibility canary workflows

Add scheduled/manual non-release compatibility canaries for dependencies/providers where early warning is useful.

At minimum, cover:

  • the supported Dapper minimum;
  • current latest stable Dapper;
  • a clearly labeled forward-looking Dapper lane when a newer stable/prerelease can be resolved;
  • provider client updates that can be tested without changing the supported matrix.

Canary failures must not silently redefine support. They are early-warning evidence only.

Keep the supported/certified matrix in COMPATIBILITY.md distinct from canary experiments.

4. Add performance regression reporting

Use the existing BenchmarkDotNet project to establish repeatable baselines for materialization hot paths, including where applicable:

  • historical root-level type mapping;
  • runtime QueryMapped* materialization;
  • generated materialization;
  • multi-mapping;
  • converter-enabled materialization.

Add a scheduled/manual comparison workflow that records machine-readable benchmark output and highlights material regressions.

Do not make noisy hosted-runner microbenchmarks a required PR gate unless repeatability has been demonstrated. The initial implementation may be report-only with explicit thresholds and artifacts; any hard-fail threshold must be justified by measured variance.

5. Document the governance model

Document how maintainers intentionally:

  • add/change public APIs;
  • update shipped/unshipped API snapshots;
  • interpret nullable annotations;
  • interpret canary failures;
  • evaluate benchmark regressions.

Out of scope

  • Changing the minimum target framework solely to enable nullable reference types.
  • Treating prerelease dependency canaries as supported versions.
  • Replacing package compatibility validation.
  • Failing normal PRs on unstable/noisy benchmarks.
  • Large public API redesigns unrelated to annotations/governance.

Definition of Ready (DoR)

  • Current package validation is green.
  • Current public package set is known and matches the package catalog.
  • Current compiler/language versions can support the selected nullable/API analyzer approach without changing consumer TFMs.
  • Existing BenchmarkDotNet scenarios run successfully and produce machine-readable output.
  • Current CI has a suitable scheduled/manual workflow pattern for canary and benchmark jobs.

Acceptance criteria

Public API

  • Every shipped library has an explicit checked-in API baseline or equivalent.
  • An unapproved public API change causes CI validation to fail.
  • An intentional additive API change has a documented update path.

Nullability

  • Maintained public projects compile under the selected nullable enforcement level.
  • Public nullable annotations match actual behavior for representative mapping/query APIs.
  • No large set of blanket suppressions is introduced.

Compatibility canary

  • Scheduled/manual canary execution is separate from the supported release matrix.
  • Canary output clearly identifies supported vs experimental dependency versions.
  • Canary failure does not change package support claims automatically.

Performance

  • Benchmark results are emitted in a machine-readable artifact.
  • Current-vs-baseline comparison identifies material changes.
  • Thresholds/reporting behavior are documented and calibrated to observed variance.

Definition of Done (DoD)

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions