Skip to content

CrossAppGuardCiGateTests scans only *.cs, so a cross-app reference expressed as an MSBuild Compile Include is invisible to it #3063

Closed

Description

@erikdarlingdata

Lite.Tests/CrossAppGuardCiGateTests.cs exists to require that when one SKU's test project reads the other's source, that read is reachable by the CI path filters. It cannot see a cross-app reference expressed in MSBuild.

The mechanism, read from source

Its collector does:

foreach (var file in Directory.EnumerateFiles(projectRoot, "*.cs", SearchOption.AllDirectories))

and then matches path string literals inside that C#:

Regex.Matches(text, "\"(" + Regex.Escape(otherApp) + "[/\\\\][^\"]+)\"")
Regex.Matches(text, @"Path\.Combine\(\s*""" + Regex.Escape(otherApp) + @"""\s*,([^)]*)\)")

So it detects a cross-app read written as "Darling/Darling.Tests/X.cs" or Path.Combine("Darling", "Darling.Tests", "X.cs") inside a .cs file. It never opens the .csproj.

The reference it misses

PR #3059 (#3052) shares one file between the SKUs with a linked compile rather than a copy:

<Compile Include="..\Darling\Darling.Tests\CSharpSourceWalker.cs" Link="CSharpSourceWalker.cs" />

That is a cross-app read of exactly the kind this guard exists to require be filter-reachable, and it is structurally invisible to it — not because the path spelling is unusual, but because the guard's population is *.cs and this lives in project XML.

Why nothing is broken today, and why it still matters

The reference is covered: the whole-tree-guards job runs regardless of area filters, and #3059's body records why a darling-filter entry was rejected — it would gate live-PostgreSQL work on all 298 Lite test files. So the CI reachability the guard demands is satisfied by a different route.

What is missing is the guard's ability to know that. The next linked compile between the SKUs gets no assertion at all, and the failure mode is the one this guard was written to prevent: a cross-app read whose CI reachability nobody checked.

Note the failure direction, because it decides the urgency. This guard fails toward not noticing — a missed reference is silent. That is the dangerous direction (see the reasoning in #3052 about the same filter being loud when it drives an assertion and silent when it drives a number), which is why it is worth fixing even though nothing is currently unguarded.

Fix

Widen the population to include the project files — *.csproj at minimum, and consider Directory.Build.props/.targets if either carries item groups. The literal-matching regexes need a sibling for MSBuild Include= attributes, where the separator is \ and the path is relative (..\Darling\…) rather than repo-rooted, so the existing anchors will not match as written.

Whatever shape it takes, floor the population and report what it scanned — a widened collector that reads no .csproj files would pass exactly as it does now.

Provenance

Flagged by the #3052 lane while introducing the linked compile, and deliberately not filed by it. Its framing was that the detector "keys on Lite/ and Darling/ while Lite.Tests is a sibling of Lite"; reading the source shows the sibling relationship is not the operative cause — the *.cs-only population is. Corrected here so the fix targets the right thing.

Activity

  1. added a commit that references this issue on Sep 6, 2026
    ff9d4ad
  2. erikdarlingdata commented on Sep 6, 2026

    @erikdarlingdata
    OwnerAuthor

    Claude posting for Erik Darling

    Fixed by #3065, merged to dev as ff9d4ad50b8. Closing by hand — a closing keyword in a PR body does not fire when the PR targets dev rather than the repository's default branch.

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