Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion .github/workflows/publish-from-manifest.yml
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,9 @@ jobs:
run: dotnet restore

- name: Build
run: dotnet build --configuration Release --no-restore
env:
VERSION: ${{ steps.version.outputs.version }}
run: dotnet build --configuration Release --no-restore -p:Version="$VERSION"

- name: Test
run: dotnet test --configuration Release --no-build
Expand Down
2 changes: 1 addition & 1 deletion release-please-config.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
"packages": {
".": {
"release-type": "simple",
"release-as": "2.0.1",
"release-as": "2.0.2",
"changelog-sections": [
{ "type": "feat", "section": "Features" },
{ "type": "fix", "section": "Bug Fixes" },
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,16 @@
Condition="'%(Analyzer.NuGetPackageId)' == '...'" does not survive the
SDK's analyzer item flow reliably.
-->
<!--
BeforeTargets="_HandlePackageFileConflicts" mirrors the main package's
guard. When the bundled-in-main analyzer and this standalone analyzer
coexist in @(Analyzer), MSBuild's conflict resolution discards one
before CoreCompile. By filtering before that, this target ensures the
consumer-property contract holds regardless of which copy MSBuild
would have picked.
-->
<Target Name="ZeroAllocAuthorizationGenerator_RemoveAnalyzerWhenNotOwner"
BeforeTargets="CoreCompile"
BeforeTargets="_HandlePackageFileConflicts"
Condition="'$(ZeroAllocAuthorizationOwnsPolicies)' != 'true'">
<ItemGroup>
<Analyzer Remove="@(Analyzer->WithMetadataValue('NuGetPackageId','ZeroAlloc.Authorization.Generator'))" />
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,8 +30,21 @@
Condition="'%(Analyzer.NuGetPackageId)' == '...'" does not survive the
SDK's analyzer item flow reliably.
-->
<!--
BeforeTargets="_HandlePackageFileConflicts" is load-bearing. The bundled
analyzer in ZeroAlloc.Authorization and the analyzer in the standalone
ZeroAlloc.Authorization.Generator package ship the same DLL filename
(ZeroAlloc.Authorization.Generator.dll) at the same NuGet path
(analyzers/dotnet/cs/). MSBuild's _HandlePackageFileConflicts target
dedupes them by AssemblyVersion and discards one — the survivor carries
only its own NuGetPackageId metadata. Firing AT _HandlePackageFileConflicts
(or later, at CoreCompile) leaves the filter chasing a dropped item.
Firing BEFORE conflict resolution removes the bundled first, no conflict
triggers, and the standalone survives. This was the root cause of the
2.0.1 regression that produced no generator output in consumer builds.
-->
<Target Name="ZeroAllocAuthorization_FilterAnalyzersByConsumerProperties"
BeforeTargets="CoreCompile">
BeforeTargets="_HandlePackageFileConflicts">
<ItemGroup Condition="'$(ZeroAllocAuthorizationDisableBundledAnalyzer)' == 'true'">
<Analyzer Remove="@(Analyzer->WithMetadataValue('NuGetPackageId','ZeroAlloc.Authorization'))" />
</ItemGroup>
Expand Down
39 changes: 38 additions & 1 deletion tests/ZeroAlloc.Authorization.PackSmoke/PackSmokeTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,39 @@ public void Split_package_pattern_builds_without_CS0121()
Assert.DoesNotContain("CS0121", build.StdOut, StringComparison.Ordinal);
}

[Fact]
public void Split_package_pattern_survives_assemblyversion_mismatch()
{
// Regression test for the 2.0.1 publish-pipeline bug. The bundled-in-main
// analyzer was packed by release-please.yml with -p:Version=2.0.1 (high
// AssemblyVersion). The standalone Generator package was packed by
// publish-from-manifest.yml without -p:Version (default 1.0.0
// AssemblyVersion). MSBuild's _HandlePackageFileConflicts target picked
// the bundled (higher AssemblyVersion wins) and discarded the standalone.
// The DisableBundled guard then removed the bundled too, leaving no
// analyzer at all. The fix moves the guard to fire BEFORE
// _HandlePackageFileConflicts so the bundled is gone before conflict
// resolution sees it; the standalone survives regardless of which copy
// would have won.
var repoRoot = LocateRepoRoot();

// Force a high AssemblyVersion on the bundled DLL (via main package)
// and a low one on the standalone Generator. Reproduces production.
PackProject(Path.Combine(repoRoot, "src/ZeroAlloc.Authorization/ZeroAlloc.Authorization.csproj"),
assemblyVersion: "9.9.9");
PackProject(Path.Combine(repoRoot, "src/ZeroAlloc.Authorization.Generator/ZeroAlloc.Authorization.Generator.csproj"),
assemblyVersion: "1.0.0");

ScaffoldTemplate(useStandaloneGenerator: true);

var apiCsproj = Path.Combine(_workDir, "src/TestApp.Api/TestApp.Api.csproj");
var build = RunDotnet($"build \"{apiCsproj}\" -c Release", _workDir);
Assert.True(build.ExitCode == 0,
$"Build must succeed regardless of AssemblyVersion ordering between bundled and standalone analyzers.\nSTDOUT:\n{build.StdOut}\nSTDERR:\n{build.StdErr}");
Assert.DoesNotContain("CS0121", build.StdOut, StringComparison.Ordinal);
Assert.DoesNotContain("CS0234", build.StdOut, StringComparison.Ordinal);
}

[Fact]
public void Bundled_only_pattern_still_works_for_2_0_0_consumers()
{
Expand All @@ -80,9 +113,13 @@ public void Bundled_only_pattern_still_works_for_2_0_0_consumers()
}

private void PackProject(string csproj)
=> PackProject(csproj, assemblyVersion: null);

private void PackProject(string csproj, string? assemblyVersion)
{
var versionArg = assemblyVersion is null ? "" : $" -p:Version={assemblyVersion}";
var result = RunDotnet(
$"pack \"{csproj}\" -c Release -p:PackageVersion={_testVersion} -o \"{_feed}\"",
$"pack \"{csproj}\" -c Release -p:PackageVersion={_testVersion}{versionArg} -o \"{_feed}\"",
Environment.CurrentDirectory);
Assert.True(result.ExitCode == 0, $"Pack failed for {csproj}:\n{result.StdOut}\n{result.StdErr}");
}
Expand Down
Loading