Skip to content

test: add a consumer smoke test that exercises delivery, not code - #9

Merged
CaffeinatedCoder merged 1 commit into
ci/pin-actions-dependabotfrom
test/consumer-smoke-test
Aug 16, 2026
Merged

CaffeinatedCoder merged 1 commit into
ci/pin-actions-dependabotfrom
test/consumer-smoke-test

Conversation

@CaffeinatedCoder

Copy link
Copy Markdown
Owner

Stacked on #5 (both touch the workflows); retargets to main once that merges. Port of EFCore.ComplexIndexes' test/consumer-smoke-test.sh, adapted for a runtime library.

Why

Every layer of the suite references the projects directly. A ProjectReference hides exactly what breaks for a consumer of the package: a satellite whose nuspec fails to declare the core package, a version range that lets NuGet resolve a different core than the one built here, a type public in the project and missing from the package, a plugin that registers through a project reference and not through the assembly a consumer restores. Each packs cleanly and restores cleanly, and the first person to notice is a consumer.

What

test/consumer-smoke-test.sh packs the four packages, restores them into throwaway projects created outside the repository (inside it, Directory.Build.props would apply), compiles real code against them, runs it, and asserts on content — printed output and translated SQL — never on the exit code alone.

Two consumers:

  • core only — parse → canonical literal, Intersect/Overlaps, JSON round trip through AddRangeConverters(), StringSet canonical form and membership.
  • CodoMetis.ValueRanges.EFCore.PostgreSQL.NodaTime — pulls all four through the nuspec chain; the chain is asserted from dotnet list package --include-transitive (each id present, at this version). Then ToQueryString() (never connects) for a BCL range predicate ("Period" @> DATE '2024-06-15'), a NodaTime range predicate ("Stay" @> DATE …) and a value-set predicate ("Tags" @> ARRAY['x']::text[]) — translations that only exist if the plugins registered from the packaged assemblies.

Load-bearing and carried over from EFCore.ComplexIndexes, where each was learned the hard way: NUGET_PACKAGES redirected to a private folder (NuGet resolves id+version from the global cache before any source, so a locally built 6.2.0 is otherwise shadowed by whatever 6.2.0 was restored before — including nuget.org's); package source mapping in the generated nuget.config (this repo's ids from the local feed only, everything else from nuget.org — restricting the whole restore to the feed fails with NU1101).

Wired into both workflows in both invocation modes: a consumer job on every PR that packs its own feed, and a step in the pack job and in the release gate that is handed the pre-built dist — the artifacts published are the artifacts tested. The script builds before it packs, so it works with or without GeneratePackageOnBuild (#7 removes it).

Verified

  • Passes locally in both modes (own feed; pre-built dist).
  • verify-the-guard (delivery): sabotaging the mechanism — the NodaTime satellite no longer calling UseValueRanges() — fails the run.
  • actionlint clean on both workflows.

CLAUDE.md gets a paragraph so the private-cache and source-mapping choices don't get "simplified" away.

🤖 Generated with Claude Code

Every layer of the suite references the projects directly. A
ProjectReference hides exactly what breaks for a consumer of the package:
a satellite whose nuspec fails to declare the core package, a version
range that lets NuGet resolve a different core than the one built here, a
type public in the project and missing from the package, a plugin that
registers through a project reference and not through the assembly a
consumer restores. Each packs cleanly and restores cleanly, and the first
person to notice is a consumer.

test/consumer-smoke-test.sh packs the four packages, restores them into
throwaway projects created outside the repository — inside it,
Directory.Build.props would apply and they would stop resembling anything
a consumer builds — compiles real code against them, runs it, and asserts
on what it prints and on the SQL the EF plugins translate. Never on the
exit code alone. Two consumers: core only (parse, algebra, JSON round
trip, value set canonical form), and the NodaTime EF satellite, which
pulls all four through the nuspec chain — the chain itself is asserted
from `dotnet list package --include-transitive`, each id at this version —
and translates a BCL range, a NodaTime range and a value set predicate to
SQL through ToQueryString, which never connects.

Two things carried over from the sibling repository because they were
learned the hard way there: NUGET_PACKAGES redirected to a private folder,
since NuGet resolves id+version from the global cache before any source
and a locally built package is otherwise shadowed by whatever build of
that version was restored before; and package source mapping in the
generated nuget.config, so this repository's ids come from the local feed
only and everything else from nuget.org — restricting the whole restore
to the local feed fails with NU1101 on the transitive dependencies.

Wired into both workflows in both invocation modes: a `consumer` job on
every PR that packs its own feed, and a step in the pack job and in the
release gate that is handed the pre-built dist — the artifacts published
are the artifacts tested. The script builds before it packs, so it works
whether or not GeneratePackageOnBuild is set.

Verified: passes in both modes locally. Sabotaging the mechanism — the
NodaTime satellite no longer calling UseValueRanges() — fails the run.
actionlint clean.

Co-Authored-By: Claude Fable 5 <[email protected]>
@CaffeinatedCoder

Copy link
Copy Markdown
Owner Author

Dispatched run for this branch (base isn't main, so no PR-triggered CI): https://github.com/CaffeinatedCoder/CodoMetis.ValueRanges/actions/runs/31944864439 — green in both modes: the new Consumer smoke test job (packs its own feed) and the step in Pack (pre-built dist). Once this is on main, Consumer smoke test is a candidate required check for branch protection. After #5 merges, Update branch to get the checks here.

@CaffeinatedCoder
CaffeinatedCoder merged commit acb5628 into ci/pin-actions-dependabot Aug 16, 2026
5 checks passed
CaffeinatedCoder added a commit that referenced this pull request Aug 16, 2026
…smoke-test

ci: land the SHA pins, Dependabot and the consumer smoke test on main (recovers #5, #9)
@CaffeinatedCoder
CaffeinatedCoder deleted the test/consumer-smoke-test branch August 16, 2026 17:59
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant