Skip to content

rulesets subdirectory missing from published NetAnalyzers nupkg #54046

Closed

Description

@gt-dbechtold

Describe the bug

"rulesets" subdirectory (and contents) are missing from published Microsoft.CodeAnalysis.NetAnalyzers packages for versions 10.*.

To Reproduce

I looked through many different 10.x versions of the nuget package, but did not see the "rulesets" subdirectory. On the other hand, I see the "rulesets" subdirectory in the 9.0.0 package version.

Although the "rulesets" directory is not present in the published NuGet package, the "rulesets" directory exists when I build the NuGet package locally on Windows using Visual Studio 2026:

  • Clone this dotnet/sdk repository.
  • Check out branch release/10.0.2xx.
  • Open src\Microsoft.CodeAnalysis.NetAnalyzers\Microsoft.CodeAnalysis.NetAnalyzers.slnx in Visual Studio (I used VS 2026 18.4.3).
  • Change solution configuration to "Release".
  • Right click on Microsoft.CodeAnalysis.NetAnalyzers.Package project and select Pack. Wait for packing to complete.
  • Using File Explorer, go look in "Microsoft.CodeAnalysis.NetAnalyzers.10.0.202-dev.nupkg" archive under artifacts\packages\Release\Shipping directory on disk (relative to repository root directory).
  • The "rulesets" subdirectory exists here. Why isn't it in the NuGet package published on nuget.org??

Remarks

I maintain an application that makes use of the ruleset files, so I am dismayed to find them missing.

Activity

  1. baronfel commented on Apr 23, 2026

    @baronfel
    Member

    bad bot, this isn't nuget-related.

  2. cremor commented on May 12, 2026

    @cremor

    It would be good to extend this issue to all subdirectories which are missing in the 10.x packages.

    Then you could also note what other issues this packaging problem causes. What I've found so far:

  3. added this to the 11.0.1xx milestone on Aug 23, 2026
  4. added and removed
    untriagedRequest triage from a team member
    on Aug 23, 2026
  5. jeffhandley commented on Aug 23, 2026

    @jeffhandley
    Member

    Thanks for reporting this @gt-dbechtold. I confirmed this regressed in .NET 10.

  6. jeffhandley commented on Aug 23, 2026

    @jeffhandley
    Member

    Regression boundary and inception

    Last known good: 10.0.0-preview.25380.108, published 2025-08-12T17:26:03Z from VMR commit 30000d883e06c122311a66894579bc12329a09d4.

    First known bad: 10.0.100-rc.1.25451.107, published 2025-09-09T13:40:57Z from VMR commit 2db1f5ee2bdda2e8d873769325fabede32e420e0.

    Inception: dotnet/sdk#50167, "Move Microsoft.CodeAnalysis.NetAnalyzers from roslyn-analyzers into sdk", merged 2025-08-15T10:57:03Z as e14d0e3087b5c01d4bc4327552441e7257e98415. This merge falls exactly between the last-good and first-bad package publications.

    The migration added all of the following in the same project:

    <None Include="$(GeneratedRulesetsDir)/**/*" Pack="true" PackagePath="/rulesets" />
    <None Include="$(GeneratedEditorconfigsDir)/**/*" Pack="true" PackagePath="/editorconfig" />
    <None Include="$(GeneratedGlobalAnalyzerConfigsDir)/**/*"
          Pack="true" PackagePath="/buildTransitive/config" />
    <None Include="$(PackagePropsTargetsFileDir)/**/*"
          Pack="true" PackagePath="/buildTransitive" />

    and:

    <Target Name="GenerateAnalyzerConfigAndDocumentationFiles"
            BeforeTargets="AfterBuild"
            DependsOnTargets="ResolveProjectReferences">

    The four globs are evaluated before the clean build generates their directories. The generation target runs later during build, so the files exist too late to join the already evaluated None items used by Pack. A subsequent project evaluation with warm outputs can see the files, explaining why the issue author's Visual Studio/local pack contained them while clean official packages did not.

    The first-bad VMR source contains the same ordering. Current main still has these lines at src/Microsoft.CodeAnalysis.NetAnalyzers/src/Microsoft.CodeAnalysis.NetAnalyzers.Package.csproj lines 17-22, 48-51, and 63-103. git blame attributes the generated-directory properties and four package globs to the migration commit. No package-layout test covering these paths was found.

    Classification:

    • Regression, not an inception-only missing feature.
    • Introduced for RC1 by the repository migration.
    • Affects every published RC/stable 10.x package tested, across 1xx/2xx/3xx/4xx servicing bands.
    • Still present on main, so future package production remains exposed.

    Migration scope and sibling-package risk

    The complete 1,515-file dotnet/sdk#50167 migration contains exactly one packable NuGet project: src/Microsoft.CodeAnalysis.NetAnalyzers/src/Microsoft.CodeAnalysis.NetAnalyzers.Package.csproj. That project explicitly sets <IsPackable>true</IsPackable> and <PackageId>Microsoft.CodeAnalysis.NetAnalyzers</PackageId>. No other package project or .nuspec moved into dotnet/sdk in that pull request.

    The migration also brought over the common, C#, and Visual Basic analyzer assembly projects, but they are not separate NuGet packages. The one package project bundles all three DLLs through PackAsAnalyzer project references. Consequently, the missing generated assets affect the integration behavior of the whole Microsoft.CodeAnalysis.NetAnalyzers package, not only CA1416: package-provided AnalysisMode/AnalysisLevel global configs, rulesets, editorconfigs, duplicate-analyzer suppression props, and analyzer-visible MSBuild properties are all absent.

    Migrated artifact Separate NuGet package? Uses the failing evaluation-time generated-file globs? Assessment
    Microsoft.CodeAnalysis.NetAnalyzers.Package.csproj Yes Yes Confirmed affected package
    Common/C#/VB analyzer projects No; three DLLs bundled into the package above No Their analyzers ship, but package integration assets are missing
    Microsoft.CodeAnalysis.NetAnalyzers.Setup No; Visual Studio setup/VSIX project No Includes analyzer DLL output groups directly; not exposed to this exact pack-ordering defect
    SDK inbox/redist integration No No GenerateLayout.targets copies generated props/targets and global configs directly from build artifacts and errors when those item sets are empty; independent controls show inbox CA1416 still works

    The retired dotnet/roslyn-analyzers repository also contained other analyzer families—Microsoft.CodeAnalysis.Analyzers, Microsoft.CodeAnalysis.BannedApiAnalyzers, PerformanceSensitiveAnalyzers, PublicApiAnalyzers, Roslyn.Diagnostics.Analyzers, and Text.Analyzers—but dotnet/sdk#50167 did not move their package projects into dotnet/sdk. There is therefore no sibling NuGet package moved in the same change that is exposed to this exact static-glob/late-generation failure.

    The appropriate audit scope is the single Microsoft.CodeAnalysis.NetAnalyzers package across all generated asset groups, plus a guard against future package migrations reusing this pattern. The fix should add generated Pack items dynamically after generation and before NuGet gathers package files, then validate a clean one-pass pack. Warm build-then-pack testing is insufficient because pre-existing outputs mask the defect.

    Recommended fix approach

    1. Move inclusion of the generated package files into a target that runs after generation and before NuGet gathers pack items (for example, before GenerateNuspec), rather than relying on evaluation-time globs.
    2. Add a clean-pack regression assertion for all four package mappings: rulesets, editorconfig, buildTransitive/config, and the three root buildTransitive props/targets files.
    3. Validate a clean package, not a warm two-step local pack.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Type

No type

Projects

No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions