Repository navigation
test: add a consumer smoke test that exercises delivery, not code - #9
Merged
CaffeinatedCoder merged 1 commit intoAug 16, 2026
Merged
Conversation
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]>
Owner
Author
|
Dispatched run for this branch (base isn't |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Stacked on #5 (both touch the workflows); retargets to
mainonce 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
ProjectReferencehides 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.shpacks the four packages, restores them into throwaway projects created outside the repository (inside it,Directory.Build.propswould 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:
Intersect/Overlaps, JSON round trip throughAddRangeConverters(),StringSetcanonical form and membership.CodoMetis.ValueRanges.EFCore.PostgreSQL.NodaTime— pulls all four through the nuspec chain; the chain is asserted fromdotnet list package --include-transitive(each id present, at this version). ThenToQueryString()(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_PACKAGESredirected 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 generatednuget.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
consumerjob 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-builtdist— the artifacts published are the artifacts tested. The script builds before it packs, so it works with or withoutGeneratePackageOnBuild(#7 removes it).Verified
dist).UseValueRanges()— fails the run.actionlintclean 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