Skip to content
Draft
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
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should include also the developer manifest too, just in case.

Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
$(CollectUpToDateCheckInputDesignTimeDependsOn);
ResolveStaticWebAssetsConfiguration;
ResolveProjectStaticWebAssets;
ResolveReferencedProjectsStaticWebAssetsConfiguration;
CollectStaticWebAssetInputsDesignTime;
</CollectUpToDateCheckInputDesignTimeDependsOn>
<CollectUpToDateCheckOutputDesignTimeDependsOn>
Expand Down Expand Up @@ -61,6 +62,7 @@

<ItemGroup>
<UpToDateCheckOutput Include="$(StaticWebAssetBuildManifestPath)" Set="StaticWebAssets" />
<UpToDateCheckOutput Include="$(StaticWebAssetEndpointsBuildManifestPath)" Set="StaticWebAssets" />
</ItemGroup>

</Target>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -46,14 +46,42 @@ Copyright (c) .NET Foundation. All rights reserved.
<Output TaskParameter="TargetOutputs" ItemName="_ReferencedProjectsConfiguration" />
</MSBuild>

<!-- During VS design-time builds (DesignTimeBuild=true), project references typically have BuildReference=false
so _StaticWebAssetProjectReference is empty and _ReferencedProjectsConfiguration is not populated.
To correctly populate the up-to-date check tracking file on initial project load (before any build
has occurred), we query referenced projects for their manifest paths directly. This is safe because
GetStaticWebAssetsProjectConfiguration only reads MSBuild properties and does not trigger a build.
The condition on _ReferencedProjectsConfiguration ensures this path only runs when the regular
build-time path produced no results, preventing duplicate entries. -->
<ItemGroup Condition="'$(BuildingInsideVisualStudio)' == 'true' and '$(DesignTimeBuild)' == 'true' and '@(_ReferencedProjectsConfiguration)' == '' and '@(ProjectReferenceWithConfiguration)' != ''">
<_StaticWebAssetDesignTimeProjectReference Include="@(_MSBuildProjectReferenceExistent)" />
</ItemGroup>

<MSBuild
Condition="'$(BuildingInsideVisualStudio)' == 'true' and '$(DesignTimeBuild)' == 'true' and '@(_StaticWebAssetDesignTimeProjectReference)' != ''"
Targets="GetStaticWebAssetsProjectConfiguration"
Properties="%(_StaticWebAssetDesignTimeProjectReference.SetConfiguration);%(_StaticWebAssetDesignTimeProjectReference.SetPlatform);%(_StaticWebAssetDesignTimeProjectReference.SetTargetFramework)"
RemoveProperties="%(_StaticWebAssetDesignTimeProjectReference.GlobalPropertiesToRemove);$(_GlobalPropertiesToRemoveFromProjectReferences)"
Projects="@(_StaticWebAssetDesignTimeProjectReference)"
BuildInParallel="$(BuildInParallel)"
SkipNonexistentTargets="true">

<Output TaskParameter="TargetOutputs" ItemName="_DesignTimeReferencedProjectsConfiguration" />
</MSBuild>

<ItemGroup Condition="'$(BuildingInsideVisualStudio)' == 'true'">
<!-- From real builds (BuildReference=true path) -->
<_ReferenceManifestPath Include="@(_ReferencedProjectsConfiguration->'%(BuildManifestPath)')" Condition="'%(_ReferencedProjectsConfiguration.BuildManifestPath)' != ''" />
<_ReferenceManifestPath Include="@(_ReferencedProjectsConfiguration->'%(EndpointsBuildManifestPath)')" Condition="'%(_ReferencedProjectsConfiguration.EndpointsBuildManifestPath)' != ''" />
<!-- From design-time builds (all references path, to fix timing bug on initial VS load) -->
<_ReferenceManifestPath Include="@(_DesignTimeReferencedProjectsConfiguration->'%(BuildManifestPath)')" Condition="'%(_DesignTimeReferencedProjectsConfiguration.BuildManifestPath)' != ''" />
<_ReferenceManifestPath Include="@(_DesignTimeReferencedProjectsConfiguration->'%(EndpointsBuildManifestPath)')" Condition="'%(_DesignTimeReferencedProjectsConfiguration.EndpointsBuildManifestPath)' != ''" />
</ItemGroup>

<WriteLinesToFile Condition="'$(BuildingInsideVisualStudio)' == 'true'"
File="$(StaticWebAssetReferencesUpToDateCheckManifestPath)"
Lines="@(_ReferenceManifestPath)"
Overwrite="false"
Overwrite="true"
WriteOnlyWhenDifferent="true" />

<MergeConfigurationProperties
Expand Down Expand Up @@ -97,6 +125,7 @@ Copyright (c) .NET Foundation. All rights reserved.
<AdditionalPublishPropertiesToRemove>$(StaticWebAssetsAdditionalPublishPropertiesToRemove)</AdditionalPublishPropertiesToRemove>
<!-- Build manifest -->
<BuildManifestPath>$([System.IO.Path]::GetFullPath('$(StaticWebAssetBuildManifestPath)'))</BuildManifestPath>
<EndpointsBuildManifestPath>$([System.IO.Path]::GetFullPath('$(StaticWebAssetEndpointsBuildManifestPath)'))</EndpointsBuildManifestPath>
</_StaticWebAssetThisProjectConfiguration>
</ItemGroup>
</Target>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -51,8 +51,9 @@ public void CollectUpToDateCheckInputOutputsDesignTime_ReportsAddedFiles()
var outputFilePath = Path.Combine(build.GetIntermediateDirectory().FullName, "StaticWebAssetsUTDCOutput.txt");
new FileInfo(outputFilePath).Should().Exist();
var outputFiles = File.ReadAllLines(outputFilePath);
outputFiles.Should().ContainSingle();
Path.GetFileName(outputFiles[0]).Should().Be("staticwebassets.build.json");
outputFiles.Should().HaveCount(2);
outputFiles.Should().Contain(x => Path.GetFileName(x) == "staticwebassets.build.json");
outputFiles.Should().Contain(x => Path.GetFileName(x) == "staticwebassets.build.endpoints.json");
}

[Fact]
Expand Down Expand Up @@ -86,8 +87,9 @@ public void CollectUpToDateCheckInputOutputsDesignTime_ReportsRemovedFiles_Once(
var outputFilePath = Path.Combine(build.GetIntermediateDirectory().FullName, "StaticWebAssetsUTDCOutput.txt");
new FileInfo(outputFilePath).Should().Exist();
var outputFiles = File.ReadAllLines(outputFilePath);
outputFiles.Should().ContainSingle();
Path.GetFileName(outputFiles[0]).Should().Be("staticwebassets.build.json");
outputFiles.Should().HaveCount(2);
outputFiles.Should().Contain(x => Path.GetFileName(x) == "staticwebassets.build.json");
outputFiles.Should().Contain(x => Path.GetFileName(x) == "staticwebassets.build.endpoints.json");
}

[Fact]
Expand All @@ -105,22 +107,59 @@ public void CollectUpToDateCheckInputOutputsDesignTime_IncludesReferencedProject
var msbuild = CreateMSBuildCommand(
ProjectDirectory,
"AppWithP2PReference",
"ResolveStaticWebAssetsConfiguration;ResolveProjectStaticWebAssets;CollectStaticWebAssetInputsDesignTime;CollectStaticWebAssetOutputsDesignTime");
"ResolveStaticWebAssetsConfiguration;ResolveProjectStaticWebAssets;ResolveReferencedProjectsStaticWebAssetsConfiguration;CollectStaticWebAssetInputsDesignTime;CollectStaticWebAssetOutputsDesignTime");

msbuild.ExecuteWithoutRestore("/p:DesignTimeBuild=true", "/p:BuildingInsideVisualStudio=true", "/bl:design.binlog").Should().Pass();

// Check the contents of the input and output files
var inputFilePath = Path.Combine(build.GetIntermediateDirectory().FullName, "StaticWebAssetsUTDCInput.txt");
new FileInfo(inputFilePath).Should().Exist();
var inputFiles = File.ReadAllLines(inputFilePath);
inputFiles.Should().HaveCount(1);
inputFiles.Should().HaveCount(2);
inputFiles.Should().Contain(Path.Combine(ProjectDirectory.Path, "ClassLibrary", "obj", "Debug", DefaultTfm, "staticwebassets.build.json"));
inputFiles.Should().Contain(Path.Combine(ProjectDirectory.Path, "ClassLibrary", "obj", "Debug", DefaultTfm, "staticwebassets.build.endpoints.json"));

var outputFilePath = Path.Combine(build.GetIntermediateDirectory().FullName, "StaticWebAssetsUTDCOutput.txt");
new FileInfo(outputFilePath).Should().Exist();
var outputFiles = File.ReadAllLines(outputFilePath);
outputFiles.Should().HaveCount(2);
outputFiles.Should().Contain(x => Path.GetFileName(x) == "staticwebassets.build.json");
outputFiles.Should().Contain(x => Path.GetFileName(x) == "staticwebassets.build.endpoints.json");
}

[Fact]
public void CollectUpToDateCheckInputOutputsDesignTime_IncludesReferencedProjectsManifests_OnInitialLoad()
{
// This test verifies the timing bug fix: referenced project manifest paths must be available
// in the FUTDC inputs even before a full build has occurred (i.e., on initial VS load).
// Arrange
var testAsset = "RazorAppWithP2PReference";
ProjectDirectory = AddIntrospection(CreateAspNetSdkTestAsset(testAsset));

var build = CreateBuildCommand(ProjectDirectory, "AppWithP2PReference");

var msbuild = CreateMSBuildCommand(
ProjectDirectory,
"AppWithP2PReference",
"ResolveStaticWebAssetsConfiguration;ResolveProjectStaticWebAssets;ResolveReferencedProjectsStaticWebAssetsConfiguration;CollectStaticWebAssetInputsDesignTime;CollectStaticWebAssetOutputsDesignTime");

// Run design-time targets WITHOUT a prior full build to simulate initial VS project load
msbuild.ExecuteWithoutRestore("/p:DesignTimeBuild=true", "/p:BuildingInsideVisualStudio=true", "/bl:design.binlog").Should().Pass();

// The referenced project manifest paths must be tracked as inputs, even without a prior build
var inputFilePath = Path.Combine(build.GetIntermediateDirectory().FullName, "StaticWebAssetsUTDCInput.txt");
new FileInfo(inputFilePath).Should().Exist();
var inputFiles = File.ReadAllLines(inputFilePath);
inputFiles.Should().HaveCount(2);
inputFiles.Should().Contain(Path.Combine(ProjectDirectory.Path, "ClassLibrary", "obj", "Debug", DefaultTfm, "staticwebassets.build.json"));
inputFiles.Should().Contain(Path.Combine(ProjectDirectory.Path, "ClassLibrary", "obj", "Debug", DefaultTfm, "staticwebassets.build.endpoints.json"));

var outputFilePath = Path.Combine(build.GetIntermediateDirectory().FullName, "StaticWebAssetsUTDCOutput.txt");
new FileInfo(outputFilePath).Should().Exist();
var outputFiles = File.ReadAllLines(outputFilePath);
outputFiles.Should().ContainSingle();
Path.GetFileName(outputFiles[0]).Should().Be("staticwebassets.build.json");
outputFiles.Should().HaveCount(2);
outputFiles.Should().Contain(x => Path.GetFileName(x) == "staticwebassets.build.json");
outputFiles.Should().Contain(x => Path.GetFileName(x) == "staticwebassets.build.endpoints.json");
}

private static MSBuildCommand CreateMSBuildCommand(TestAsset testAsset, string relativeProjectPath, string targets)
Expand Down
Loading