Skip to content

Add support for /t:Publish /p:NoBuild=true #2111

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Apr 4, 2018
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 @@ -36,9 +36,26 @@ Copyright (c) .NET Foundation. All rights reserved.
The main publish entry point.
============================================================
-->

<PropertyGroup Condition="'$(NoBuild)' != 'true'">
Copy link
Member

Choose a reason for hiding this comment

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

Should we use a less generic name for this property? Perhaps PublishWithoutBuild or something?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

This matches pack --no-build so I think it's worth the consistency. Otherwise it should have been PackWithoutBuilding.

<_BeforePublishTargets>Build</_BeforePublishTargets>
</PropertyGroup>

<PropertyGroup Condition="'$(NoBuild)' == 'true'">
<!-- We still need to resolve references even if we are not building during publish. -->
<!-- BuildOnlySettings are required for RAR to find satellites and dependencies -->
<_BeforePublishTargets>
BuildOnlySettings;
_PreventProjectReferencesFromBuilding;
ResolveReferences;
PrepareResourceNames;
ComputeIntermediateSatelliteAssemblies;
</_BeforePublishTargets>
</PropertyGroup>

<Target Name="Publish"
Condition="$(IsPublishable) == 'true'"
DependsOnTargets="Build;
DependsOnTargets="$(_BeforePublishTargets);
PrepareForPublish;
ComputeAndCopyFilesToPublishDirectory;
GeneratePublishDependencyFile;
Expand All @@ -49,6 +66,13 @@ Copyright (c) .NET Foundation. All rights reserved.
the published assets were copied. -->
<Message Importance="High" Text="$(MSBuildProjectName) -&gt; $([System.IO.Path]::GetFullPath('$(PublishDir)'))" />
</Target>

<!-- Don't let project reference resolution build project references in NoBuild case. -->
<Target Name="_PreventProjectReferencesFromBuilding">
<PropertyGroup>
<BuildProjectReferences>false</BuildProjectReferences>
</PropertyGroup>
</Target>

<!--
============================================================
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -80,15 +80,5 @@ public void ResolvePackageAssets_runs_incrementally()
var cacheWriteTime4 = File.GetLastWriteTimeUtc(assetsCachePath);
cacheWriteTime4.Should().NotBe(cacheWriteTime3);
}

private static void WaitForUtcNowToAdvance()
{
var start = DateTime.UtcNow;

while (DateTime.UtcNow <= start)
{
Thread.Sleep(millisecondsTimeout: 1);
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Runtime.CompilerServices;
using System.Xml.Linq;
using FluentAssertions;
using FluentAssertions.Json;
using Microsoft.Extensions.DependencyModel;
Expand All @@ -13,7 +15,6 @@
using Microsoft.NET.TestFramework.Commands;
using Newtonsoft.Json.Linq;
using Xunit;
using System.Xml.Linq;
using Xunit.Abstractions;

namespace Microsoft.NET.Publish.Tests
Expand All @@ -28,26 +29,7 @@ public GivenThatWeWantToPublishAProjectWithAllFeatures(ITestOutputHelper log) :
[MemberData(nameof(PublishData))]
public void It_publishes_the_project_correctly(string targetFramework, string [] expectedPublishFiles)
{
TestAsset testAsset = _testAssetsManager
.CopyTestAsset("KitchenSink", "KitchenSinkPublish_", targetFramework)
.WithSource()
.WithProjectChanges((path, project) =>
{
if (Path.GetFileName(path).Equals("TestApp.csproj", StringComparison.OrdinalIgnoreCase))
{
var ns = project.Root.Name.Namespace;

var targetFrameworkElement = project.Root.Elements(ns + "PropertyGroup").Elements(ns + "TargetFramework").Single();
targetFrameworkElement.SetValue(targetFramework);
}
});

testAsset.Restore(Log, "TestApp");
testAsset.Restore(Log, "TestLibrary");

var appProjectDirectory = Path.Combine(testAsset.TestRoot, "TestApp");

PublishCommand publishCommand = new PublishCommand(Log, appProjectDirectory);
PublishCommand publishCommand = GetPublishCommand(targetFramework);
publishCommand
.Execute()
.Should()
Expand Down Expand Up @@ -107,6 +89,87 @@ public void It_publishes_the_project_correctly(string targetFramework, string []
.BeEquivalentTo(baselineConfigJsonObject);
}

[Fact]
public void It_fails_when_nobuild_is_set_and_build_was_not_performed_previously()
{
var publishCommand = GetPublishCommand("netcoreapp1.0").Execute("/p:NoBuild=true");
publishCommand.Should().Fail().And.HaveStdOutContaining("MSB3030"); // "Could not copy ___ because it was not found."
}

[Theory]
[MemberData(nameof(PublishData))]
public void It_does_not_build_when_nobuild_is_set(string targetFramework, string[] expectedPublishFiles)
{
var publishCommand = GetPublishCommand(targetFramework);

// do a separate build invocation before publish
var buildCommand = new BuildCommand(Log, publishCommand.ProjectRootPath);
buildCommand.Execute().Should().Pass();

// modify all project files, which would force recompilation if we were to build during publish
WaitForUtcNowToAdvance();
foreach (string projectFile in EnumerateFiles(buildCommand, "*.csproj"))
{
File.AppendAllText(projectFile, " ");
}

// capture modification time of all binaries before publish
var modificationTimes = GetLastWriteTimesUtc(buildCommand, "*.exe", "*.dll", "*.resources", "*.pdb");
Copy link
Member

Choose a reason for hiding this comment

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

There should probably be a "sleep until current time advances" loop here.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Fixed.


// publish (with NoBuild set)
WaitForUtcNowToAdvance();
publishCommand.Execute("/p:NoBuild=true").Should().Pass();
publishCommand.GetOutputDirectory(targetFramework).Should().OnlyHaveFiles(expectedPublishFiles);

// check that publish did not modify any of the build output
foreach (var (file, modificationTime) in modificationTimes)
{
File.GetLastWriteTimeUtc(file)
.Should().Be(
modificationTime,
because: $"Publish with NoBuild=true should not overwrite {file}");
}
}

private static List<(string, DateTime)> GetLastWriteTimesUtc(MSBuildCommand command, params string[] searchPatterns)
{
return EnumerateFiles(command, searchPatterns)
.Select(file => (file, File.GetLastWriteTimeUtc(file)))
.ToList();
}

private static IEnumerable<string> EnumerateFiles(MSBuildCommand command, params string[] searchPatterns)
{
return searchPatterns.SelectMany(
pattern => Directory.EnumerateFiles(
Path.Combine(command.ProjectRootPath, ".."), // up one level from TestApp to also get TestLibrary P2P files
pattern,
SearchOption.AllDirectories));
}

private PublishCommand GetPublishCommand(string targetFramework, [CallerMemberName] string callingMethod = null)
{
TestAsset testAsset = _testAssetsManager
.CopyTestAsset("KitchenSink", callingMethod, identifier: targetFramework)
.WithSource()
.WithProjectChanges((path, project) =>
{
if (Path.GetFileName(path).Equals("TestApp.csproj", StringComparison.OrdinalIgnoreCase))
{
var ns = project.Root.Name.Namespace;

var targetFrameworkElement = project.Root.Elements(ns + "PropertyGroup").Elements(ns + "TargetFramework").Single();
targetFrameworkElement.SetValue(targetFramework);
}
});

testAsset.Restore(Log, "TestApp");

var appProjectDirectory = Path.Combine(testAsset.TestRoot, "TestApp");

return new PublishCommand(Log, appProjectDirectory);
}

private static void VerifyDependency(
DependencyContext dependencyContext,
string name,
Expand Down
11 changes: 11 additions & 0 deletions src/Tests/Microsoft.NET.TestFramework/SdkTest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
using System.Reflection;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading;
using Xunit.Abstractions;

namespace Microsoft.NET.TestFramework
Expand All @@ -20,5 +21,15 @@ protected SdkTest(ITestOutputHelper log)
{
Log = log;
}

protected static void WaitForUtcNowToAdvance()
{
var start = DateTime.UtcNow;

while (DateTime.UtcNow <= start)
{
Thread.Sleep(millisecondsTimeout: 1);
}
}
}
}