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
Original file line number Diff line number Diff line change
Expand Up @@ -841,6 +841,26 @@ Copyright (c) .NET Foundation. All rights reserved.

</Target>

<!--
============================================================
PublishItemsOutputGroup

Emit an output group containing all files that get published. This will be consumed by VS installer projects.
============================================================
-->
<PropertyGroup>
<PublishItemsOutputGroupDependsOn>
$(PublishItemsOutputGroupDependsOn);
ComputeFilesToPublish;
</PublishItemsOutputGroupDependsOn>
</PropertyGroup>

<Target Name="PublishItemsOutputGroup" DependsOnTargets="$(PublishItemsOutputGroupDependsOn)" Returns="@(PublishItemsOutputGroupOutputs)">
<ItemGroup>
<PublishItemsOutputGroupOutputs Include="@(ResolvedFileToPublish->'%(FullPath)')" TargetPath="%(ResolvedFileToPublish.RelativePath)" OutputGroup="PublishItemsOutputGroup" />
</ItemGroup>
</Target>

<!--
This target exists for back-compat with Azure Functions SDK: https://github.com/dotnet/cli/issues/10363
Because build copy-local now behaves the same as publish with respect to package dependency resolution,
Expand Down
106 changes: 106 additions & 0 deletions src/Tests/Microsoft.NET.Publish.Tests/PublishItemsOutputGroupTests.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
using System.Collections.Generic;
using System.IO;
using FluentAssertions;
using Microsoft.DotNet.Cli.Utils;
using Microsoft.NET.TestFramework;
using Microsoft.NET.TestFramework.Assertions;
using Microsoft.NET.TestFramework.Commands;
using Microsoft.NET.TestFramework.ProjectConstruction;
using Xunit;
using Xunit.Abstractions;

namespace Microsoft.NET.Publish.Tests
{
public class PublishItemsOutputGroupTests : SdkTest
{
public PublishItemsOutputGroupTests(ITestOutputHelper log) : base(log)
{
}

private readonly static List<string> FrameworkAssemblies = new List<string>()
{
"api-ms-win-core-console-l1-1-0.dll",
"System.Runtime.dll",
"WindowsBase.dll",
};

[Fact]
public void GroupPopulatedWithRid()
{
var testProject = this.SetupProject();
var testAsset = _testAssetsManager.CreateTestProject(testProject);

var restoreCommand = new RestoreCommand(Log, testAsset.Path, testProject.Name);
restoreCommand
.Execute()
.Should()
.Pass();

var buildCommand = new BuildCommand(Log, testAsset.Path, testProject.Name);
buildCommand
.Execute("/p:RuntimeIdentifier=win-x86", "/t:PublishItemsOutputGroup")
.Should()
.Pass();

var testOutputDir = new DirectoryInfo(Path.Combine(testAsset.Path, testProject.Name, "TestOutput"));
Log.WriteLine("Contents of PublishItemsOutputGroup dumped to '{0}'.", testOutputDir.FullName);

// Check for the existence of a few specific files that should be in the directory where the
// contents of PublishItemsOutputGroup were dumped to make sure it's getting populated.
testOutputDir.Should().HaveFile($"{testProject.Name}.exe");
testOutputDir.Should().HaveFiles(FrameworkAssemblies);
}

[Fact]
public void GroupNotPopulatedWithoutRid()
{
var testProject = this.SetupProject();
var testAsset = _testAssetsManager.CreateTestProject(testProject);

var restoreCommand = new RestoreCommand(Log, testAsset.Path, testProject.Name);
restoreCommand
.Execute()
.Should()
.Pass();

var buildCommand = new BuildCommand(Log, testAsset.Path, testProject.Name);
buildCommand
.Execute("/t:PublishItemsOutputGroup")
.Should()
.Pass();

var testOutputDir = new DirectoryInfo(Path.Combine(testAsset.Path, testProject.Name, "TestOutput"));
Log.WriteLine("Contents of PublishItemsOutputGroup dumped to '{0}'.", testOutputDir.FullName);

// Since no RID was specified the output group should only contain framework dependent output
testOutputDir.Should().HaveFile($"{testProject.Name}{Constants.ExeSuffix}");
testOutputDir.Should().NotHaveFiles(FrameworkAssemblies);
}

private TestProject SetupProject()
{
var testProject = new TestProject()
{
Name = "TestPublishOutputGroup",
TargetFrameworks = "netcoreapp3.0",
IsSdkProject = true,
IsExe = true
};

testProject.AdditionalProperties["RuntimeIdentifiers"] = "win-x86";

// Use a test-specific packages folder
testProject.AdditionalProperties["RestorePackagesPath"] = @"$(MSBuildProjectDirectory)\..\pkg";

// Add a target that will dump the contents of the PublishItemsOutputGroup to
// a test directory after building.
testProject.CopyFilesTargets.Add(new CopyFilesTarget(
"CopyPublishItemsOutputGroup",
"PublishItemsOutputGroup",
"@(PublishItemsOutputGroupOutputs)",
"$(MSBuildProjectDirectory)\\TestOutput"));

return testProject;
}
}
}
25 changes: 25 additions & 0 deletions src/Tests/Microsoft.NET.TestFramework/CopyFilesTarget.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
// Copyright (c) .NET Foundation and contributors. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.

namespace Microsoft.NET.TestFramework
{
/// <summary>
/// Represents a target that will copy some set of files to a given location after some other target completes.
/// Useful for verifying the contents of an output group in a test.
/// </summary>
public class CopyFilesTarget
{
public CopyFilesTarget(string targetName, string targetToRunAfter, string sourceFiles, string destination)
{
TargetName = targetName;
TargetToRunAfter = targetToRunAfter;
SourceFiles = sourceFiles;
Destination = destination;
}

public string TargetName { get; private set; }
public string TargetToRunAfter { get; private set; }
public string SourceFiles { get; private set; }
public string Destination { get; private set; }
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,8 @@ public class TestProject
public List<TestPackageReference> PackageReferences { get; } = new List<TestPackageReference>();

public List<TestPackageReference> DotNetCliToolReferences { get; } = new List<TestPackageReference>();

public List<CopyFilesTarget> CopyFilesTargets { get; } = new List<CopyFilesTarget>();

public Dictionary<string, string> SourceFiles { get; } = new Dictionary<string, string>();

Expand Down Expand Up @@ -270,6 +272,22 @@ internal void Create(TestAsset targetTestAsset, string testProjectsSourceFolder)
new XAttribute("Include", reference)));
}
}

if (this.CopyFilesTargets.Any())
{
foreach (var copyFilesTarget in CopyFilesTargets)
{
var target = new XElement(ns + "Target",
new XAttribute("Name", copyFilesTarget.TargetName),
new XAttribute("AfterTargets", copyFilesTarget.TargetToRunAfter));

target.Add(new XElement(ns + "Copy",
new XAttribute("SourceFiles", copyFilesTarget.SourceFiles),
new XAttribute("DestinationFolder", copyFilesTarget.Destination)));

projectXml.Root.Add(target);
}
}

using (var file = File.CreateText(targetProjectPath))
{
Expand Down