diff --git a/build/DependencyVersions.props b/build/DependencyVersions.props index 75567df570..0d39b545bb 100644 --- a/build/DependencyVersions.props +++ b/build/DependencyVersions.props @@ -4,7 +4,7 @@ 2.0.0-preview1-001887-00 15.2.0-preview-000047-02 2.0.0-rc4-61325-08 - 2.0.0-alpha-20170323-1 + 2.0.0-alpha-20170403-2 4.3.0-beta1-2418 1.0.0-alpha-20170130-3-281 15.1.0-preview-20170316-05 diff --git a/src/dotnet/commands/dotnet-publish/LocalizableStrings.cs b/src/dotnet/commands/dotnet-publish/LocalizableStrings.cs index 2a119fb044..c0b6d6a2f0 100644 --- a/src/dotnet/commands/dotnet-publish/LocalizableStrings.cs +++ b/src/dotnet/commands/dotnet-publish/LocalizableStrings.cs @@ -20,5 +20,7 @@ internal class LocalizableStrings public const string FilterProjOption = "profile.xml"; public const string FilterProjOptionDescription = "The XML file that contains the list of packages to be excluded from publish step."; + + public const string SelfContainedOptionDescription = "Publish the .NET Core runtime with your application so the runtime doesn't need to be installed on the target machine. Defaults to 'true' if a runtime identifier is specified."; } } diff --git a/src/dotnet/commands/dotnet-publish/PublishCommandParser.cs b/src/dotnet/commands/dotnet-publish/PublishCommandParser.cs index 2318953165..384b613cd7 100644 --- a/src/dotnet/commands/dotnet-publish/PublishCommandParser.cs +++ b/src/dotnet/commands/dotnet-publish/PublishCommandParser.cs @@ -21,16 +21,26 @@ public static Command Publish() => "-o|--output", LocalizableStrings.OutputOptionDescription, Accept.ExactlyOneArgument() - .With(name: LocalizableStrings.OutputOption) - .ForwardAsSingle(o => $"/p:PublishDir={o.Arguments.Single()}")), + .With(name: LocalizableStrings.OutputOption) + .ForwardAsSingle(o => $"/p:PublishDir={o.Arguments.Single()}")), CommonOptions.ConfigurationOption(), CommonOptions.VersionSuffixOption(), Create.Option( "--filter", LocalizableStrings.FilterProjOptionDescription, Accept.OneOrMoreArguments() - .With(name: LocalizableStrings.FilterProjOption) - .ForwardAsSingle(o => $"/p:FilterProjectFiles={string.Join("%3B", o.Arguments)}")), + .With(name: LocalizableStrings.FilterProjOption) + .ForwardAsSingle(o => $"/p:FilterProjectFiles={string.Join("%3B", o.Arguments)}")), + Create.Option( + "--self-contained", + LocalizableStrings.SelfContainedOptionDescription, + Accept.ZeroOrOneArgument() + .WithSuggestionsFrom("true", "false") + .ForwardAsSingle(o => + { + string value = o.Arguments.Any() ? o.Arguments.Single() : "true"; + return $"/p:SelfContained={value}"; + })), CommonOptions.VerbosityOption()); } } \ No newline at end of file diff --git a/test/Microsoft.DotNet.Tools.Tests.Utilities/Commands/PublishCommand.cs b/test/Microsoft.DotNet.Tools.Tests.Utilities/Commands/PublishCommand.cs index e411e83f2d..5512d752cf 100644 --- a/test/Microsoft.DotNet.Tools.Tests.Utilities/Commands/PublishCommand.cs +++ b/test/Microsoft.DotNet.Tools.Tests.Utilities/Commands/PublishCommand.cs @@ -13,7 +13,8 @@ public sealed class PublishCommand : DotnetCommand private string _output; private string _runtime; private List _profileFilterProject = new List(); - + private bool? _selfContained; + public PublishCommand WithFramework(string framework) { _framework = framework; @@ -37,12 +38,18 @@ public PublishCommand WithRuntime(string runtime) return this; } - public PublishCommand WithProFileProject(string profileproj) + public PublishCommand WithProfileProject(string profileproj) { _profileFilterProject.Add( $" --filter {profileproj}"); return this; } + public PublishCommand WithSelfContained(bool value) + { + _selfContained = value; + return this; + } + public override CommandResult Execute(string args = "") { args = $"publish {BuildArgs()} {args}"; @@ -61,7 +68,8 @@ private string BuildArgs() FrameworkOption, OutputOption, ProfileProjOption, - RuntimeOption); + RuntimeOption, + SelfContainedOption); } private string FrameworkOption => string.IsNullOrEmpty(_framework) ? "" : $"-f {_framework}"; @@ -71,5 +79,7 @@ private string BuildArgs() private string RuntimeOption => string.IsNullOrEmpty(_runtime) ? "" : $"-r {_runtime}"; private string ProfileProjOption => string.Join(" ", _profileFilterProject); + + private string SelfContainedOption => _selfContained.HasValue ? $"--self-contained:{_selfContained.Value}" : ""; } } diff --git a/test/dotnet-cache.Tests/GivenDotnetCachesAndPublishesProjects.cs b/test/dotnet-cache.Tests/GivenDotnetCachesAndPublishesProjects.cs index 92d22fbd23..1bbe8b3f00 100644 --- a/test/dotnet-cache.Tests/GivenDotnetCachesAndPublishesProjects.cs +++ b/test/dotnet-cache.Tests/GivenDotnetCachesAndPublishesProjects.cs @@ -57,7 +57,7 @@ public void ItPublishesARunnablePortableApp() new PublishCommand() .WithFramework(_tfm) .WithWorkingDirectory(testProjectDirectory) - .WithProFileProject(profileFilter) + .WithProfileProject(profileFilter) .Execute() .Should().Pass(); @@ -95,7 +95,7 @@ public void AppFailsDueToMissingCache() new PublishCommand() .WithFramework(_tfm) .WithWorkingDirectory(testProjectDirectory) - .WithProFileProject(profileFilter) + .WithProfileProject(profileFilter) .Execute() .Should().Pass(); @@ -153,8 +153,8 @@ public void ItPublishesAnAppWithMultipleProfiles() new PublishCommand() .WithFramework(_tfm) .WithWorkingDirectory(testProjectDirectory) - .WithProFileProject(profileFilter) - .WithProFileProject(profileFilter1) + .WithProfileProject(profileFilter) + .WithProfileProject(profileFilter1) .Execute() .Should().Pass(); diff --git a/test/dotnet-publish.Tests/GivenDotnetPublishPublishesProjects.cs b/test/dotnet-publish.Tests/GivenDotnetPublishPublishesProjects.cs index 289c40ccc1..3b45ab3c83 100644 --- a/test/dotnet-publish.Tests/GivenDotnetPublishPublishesProjects.cs +++ b/test/dotnet-publish.Tests/GivenDotnetPublishPublishesProjects.cs @@ -27,7 +27,7 @@ public void ItPublishesARunnablePortableApp() new RestoreCommand() .WithWorkingDirectory(testProjectDirectory) - .Execute("/p:SkipInvalidConfigurations=true") + .Execute() .Should().Pass(); new PublishCommand() @@ -62,9 +62,7 @@ public void ItPublishesARunnableSelfContainedApp() .WithFramework("netcoreapp2.0") .WithRuntime(rid) .WithWorkingDirectory(testProjectDirectory) - //Workaround for https://github.com/dotnet/cli/issues/4501 - .WithEnvironmentVariable("SkipInvalidConfigurations", "true") - .Execute("/p:SkipInvalidConfigurations=true") + .Execute() .Should().Pass(); var configuration = Environment.GetEnvironmentVariable("CONFIGURATION") ?? "Debug"; @@ -73,11 +71,7 @@ public void ItPublishesARunnableSelfContainedApp() .GetDirectory("bin", configuration, "netcoreapp2.0", rid, "publish", $"{testAppName}{Constants.ExeSuffix}") .FullName; - if (!RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) - { - //Workaround for https://github.com/dotnet/corefx/issues/15516 - Process.Start("chmod", $"u+x {outputProgram}").WaitForExit(); - } + EnsureProgramIsRunnable(outputProgram); new TestCommand(outputProgram) .ExecuteWithCapturedOutput() @@ -85,6 +79,73 @@ public void ItPublishesARunnableSelfContainedApp() .And.HaveStdOutContaining("Hello World"); } + [Fact] + public void ItPublishesARidSpecificAppSettingSelfContainedToTrue() + { + var testAppName = "MSBuildTestApp"; + var outputDirectory = PublishAppWithSelfContained(testAppName, true); + + var outputProgram = Path.Combine(outputDirectory.FullName, $"{testAppName}{Constants.ExeSuffix}"); + + EnsureProgramIsRunnable(outputProgram); + + new TestCommand(outputProgram) + .ExecuteWithCapturedOutput() + .Should().Pass() + .And.HaveStdOutContaining("Hello World"); + } + + [Fact] + public void ItPublishesARidSpecificAppSettingSelfContainedToFalse() + { + var testAppName = "MSBuildTestApp"; + var outputDirectory = PublishAppWithSelfContained(testAppName, false); + + outputDirectory.Should().OnlyHaveFiles(new[] { + $"{testAppName}.dll", + $"{testAppName}.pdb", + $"{testAppName}.deps.json", + $"{testAppName}.runtimeconfig.json", + }); + + new DotnetCommand() + .ExecuteWithCapturedOutput(Path.Combine(outputDirectory.FullName, $"{testAppName}.dll")) + .Should().Pass() + .And.HaveStdOutContaining("Hello World"); + } + + private DirectoryInfo PublishAppWithSelfContained(string testAppName, bool selfContained) + { + var testInstance = TestAssets.Get(testAppName) + .CreateInstance($"PublishesSelfContained{selfContained}") + .WithSourceFiles() + .WithRestoreFiles(); + + var testProjectDirectory = testInstance.Root; + + var rid = DotnetLegacyRuntimeIdentifiers.InferLegacyRestoreRuntimeIdentifier(); + + new PublishCommand() + .WithRuntime(rid) + .WithSelfContained(selfContained) + .WithWorkingDirectory(testProjectDirectory) + .Execute() + .Should().Pass(); + + var configuration = Environment.GetEnvironmentVariable("CONFIGURATION") ?? "Debug"; + return testProjectDirectory + .GetDirectory("bin", configuration, "netcoreapp2.0", rid, "publish"); + } + + private static void EnsureProgramIsRunnable(string path) + { + if (!RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) + { + //Workaround for https://github.com/dotnet/corefx/issues/15516 + Process.Start("chmod", $"u+x {path}").WaitForExit(); + } + } + [Fact] public void ItPublishesAppWhenRestoringToSpecificPackageDirectory() {