Skip to content

ci: fail the build when a project is missing from CritterCab.slnx#36

Merged
erikshafer merged 1 commit into
mainfrom
ci/solution-completeness-guard
Jun 26, 2026
Merged

ci: fail the build when a project is missing from CritterCab.slnx#36
erikshafer merged 1 commit into
mainfrom
ci/solution-completeness-guard

Conversation

@erikshafer

Copy link
Copy Markdown
Owner

Summary

Adds a pre-build CI guard that fails the workflow if any *.csproj on disk is absent from CritterCab.slnx, closing a silent test-discovery hole before the second service lands.

The risk this closes

CI runs dotnet restore/build/test against CritterCab.slnx, which enumerates each project with an explicit <Project Path=…/>no glob. That makes the slnx the single source of truth for what CI sees. A *.Tests.csproj added to disk but not hand-added to the slnx would silently never run, and the check would still go green.

The trap is inert today (one service, two projects) but armed to fire the moment the next roadmap build — the Telemetry service — lands with its own *.Tests.csproj. Nobody would notice from a passing check.

What changed

A single new step in .github/workflows/dotnet.yml, placed right after Checkout (before Setup .NET, so it fails at the cheapest possible point):

  • Globs every *.csproj on disk and asserts each appears in CritterCab.slnx.
  • On drift, emits a ::error:: annotation naming the offending project and exits non-zero.

This keeps the efficient single-pass slnx restore/build/test exactly as-is (chosen over the glob-driven-test alternative to preserve one source of truth shared by the IDE and CI, and to give a clear actionable failure rather than a confusing --no-build assembly-not-found error). It also catches any project drift, not just test projects — a new service's main project missing from the slnx is flagged too.

Verification

Guard logic exercised locally before commit:

  • Positive — current two projects: exits 0, no false positives.
  • Negative — simulated forgotten Telemetry service (CritterCab.Telemetry + .Telemetry.Tests not in slnx): both flagged, exits 1.

No code or .csproj touched, so the build/test baseline (build 0/0, test 11/11) is unaffected; this PR's own CI run exercises the new guard end-to-end in its real environment.

Deferred (intentionally out of scope)

Kept tightly scoped to the prioritized discovery-guard risk. Two cheap polish items from the investigation are left for separate follow-ups: TreatWarningsAsErrors (a durable behavior change) and surfacing the .trx in the PR checks step-summary (DX papercut).

CI restores, builds, and tests CritterCab.slnx explicitly — the slnx
enumerates each project with no glob, making it the single source of
truth for what CI sees. A *.Tests.csproj added to disk but not hand-
added to the slnx would silently never run, and the check would still
go green.

That trap is inert today (one service, two projects) but armed to fire
the moment the second service (Telemetry) lands with its own test
project. This adds a pre-build guard that fails CI with a clear error
if any *.csproj on disk is absent from the slnx, keeping test discovery
omission-proof as new services are added.

Guard logic verified locally: passes for the current two projects and
flags a simulated forgotten Telemetry service.
@erikshafer erikshafer self-assigned this Jun 26, 2026
@erikshafer erikshafer merged commit 8b64b42 into main Jun 26, 2026
1 check passed
@erikshafer erikshafer deleted the ci/solution-completeness-guard branch June 26, 2026 01:08
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