From a7366f586444d1dad0f72095c39d51b0dace67cc Mon Sep 17 00:00:00 2001 From: Eric Erhardt Date: Fri, 30 Sep 2016 17:47:23 -0500 Subject: [PATCH] Add support for publishing self-contained applications. Fix #4204 --- .../MSBuildTestAppPackageRefs.csproj | 25 ++++++ .../MSBuildTestAppPackageRefs/Program.cs | 12 +++ .../commands/dotnet-publish3/Program.cs | 48 +++------- .../dotnet-publish3/Publish3Command.cs | 88 +++++++++++++++++++ .../Commands/Publish3Command.cs | 29 +++++- .../GivenDotnetPublish3PublishesProjects.cs | 31 +++++++ 6 files changed, 193 insertions(+), 40 deletions(-) create mode 100644 TestAssets/TestProjects/MSBuildTestAppPackageRefs/MSBuildTestAppPackageRefs.csproj create mode 100644 TestAssets/TestProjects/MSBuildTestAppPackageRefs/Program.cs create mode 100644 src/dotnet/commands/dotnet-publish3/Publish3Command.cs diff --git a/TestAssets/TestProjects/MSBuildTestAppPackageRefs/MSBuildTestAppPackageRefs.csproj b/TestAssets/TestProjects/MSBuildTestAppPackageRefs/MSBuildTestAppPackageRefs.csproj new file mode 100644 index 000000000..575aa5f14 --- /dev/null +++ b/TestAssets/TestProjects/MSBuildTestAppPackageRefs/MSBuildTestAppPackageRefs.csproj @@ -0,0 +1,25 @@ + + + + + + Exe + netcoreapp1.0 + + + + + + + + + + 1.0.1 + + + 1.0.0-alpha-20160930-2 + + + + + \ No newline at end of file diff --git a/TestAssets/TestProjects/MSBuildTestAppPackageRefs/Program.cs b/TestAssets/TestProjects/MSBuildTestAppPackageRefs/Program.cs new file mode 100644 index 000000000..8dae6dd9e --- /dev/null +++ b/TestAssets/TestProjects/MSBuildTestAppPackageRefs/Program.cs @@ -0,0 +1,12 @@ +using System; + +namespace MSBuildTestApp +{ + public class Program + { + public static void Main(string[] args) + { + Console.WriteLine("Hello World!"); + } + } +} diff --git a/src/dotnet/commands/dotnet-publish3/Program.cs b/src/dotnet/commands/dotnet-publish3/Program.cs index fd529c677..41951d13e 100644 --- a/src/dotnet/commands/dotnet-publish3/Program.cs +++ b/src/dotnet/commands/dotnet-publish3/Program.cs @@ -1,14 +1,12 @@ // 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. -using System.Collections.Generic; using Microsoft.DotNet.Cli.CommandLine; using Microsoft.DotNet.Cli.Utils; -using Microsoft.DotNet.Tools.MSBuild; namespace Microsoft.DotNet.Tools.Publish3 { - public class Publish3Command + public partial class Publish3Command { public static int Run(string[] args) { @@ -47,43 +45,17 @@ namespace Microsoft.DotNet.Tools.Publish3 app.OnExecute(() => { - List msbuildArgs = new List(); + Publish3Command publish = new Publish3Command(); - if (!string.IsNullOrEmpty(projectArgument.Value)) - { - msbuildArgs.Add(projectArgument.Value); - } + publish.ProjectPath = projectArgument.Value; + publish.Framework = frameworkOption.Value(); + publish.Runtime = runtimeOption.Value(); + publish.OutputPath = outputOption.Value(); + publish.Configuration = configurationOption.Value(); + publish.VersionSuffix = versionSuffixOption.Value(); + publish.ExtraMSBuildArguments = app.RemainingArguments; - msbuildArgs.Add("/t:Publish"); - - if (frameworkOption.HasValue()) - { - msbuildArgs.Add($"/p:TargetFramework={frameworkOption.Value()}"); - } - - if (runtimeOption.HasValue()) - { - msbuildArgs.Add($"/p:RuntimeIdentifier={runtimeOption.Value()}"); - } - - if (outputOption.HasValue()) - { - msbuildArgs.Add($"/p:PublishDir={outputOption.Value()}"); - } - - if (configurationOption.HasValue()) - { - msbuildArgs.Add($"/p:Configuration={configurationOption.Value()}"); - } - - if (versionSuffixOption.HasValue()) - { - msbuildArgs.Add($"/p:VersionSuffix={versionSuffixOption.Value()}"); - } - - msbuildArgs.AddRange(app.RemainingArguments); - - return new MSBuildForwardingApp(msbuildArgs).Execute(); + return publish.Execute(); }); return app.Execute(args); diff --git a/src/dotnet/commands/dotnet-publish3/Publish3Command.cs b/src/dotnet/commands/dotnet-publish3/Publish3Command.cs new file mode 100644 index 000000000..c6a4cf5f5 --- /dev/null +++ b/src/dotnet/commands/dotnet-publish3/Publish3Command.cs @@ -0,0 +1,88 @@ +// 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. + +using System.Collections.Generic; +using Microsoft.DotNet.Cli.Utils; +using Microsoft.DotNet.Tools.MSBuild; +using Microsoft.DotNet.Tools.Restore3; + +namespace Microsoft.DotNet.Tools.Publish3 +{ + public partial class Publish3Command + { + public string ProjectPath { get; set; } + public string Framework { get; set; } + public string Runtime { get; set; } + public string OutputPath { get; set; } + public string Configuration { get; set; } + public string VersionSuffix { get; set; } + + public List ExtraMSBuildArguments { get; set; } + + private Publish3Command() + { + } + + public int Execute() + { + int restoreResult = EnsureRestored(); + if (restoreResult != 0) + { + throw new GracefulException("Restore failed. Please fix the errors and try publishing again."); + } + + List msbuildArgs = new List(); + + if (!string.IsNullOrEmpty(ProjectPath)) + { + msbuildArgs.Add(ProjectPath); + } + + msbuildArgs.Add("/t:Publish"); + + if (!string.IsNullOrEmpty(Framework)) + { + msbuildArgs.Add($"/p:TargetFramework={Framework}"); + } + + if (!string.IsNullOrEmpty(Runtime)) + { + msbuildArgs.Add($"/p:RuntimeIdentifier={Runtime}"); + } + + if (!string.IsNullOrEmpty(OutputPath)) + { + msbuildArgs.Add($"/p:PublishDir={OutputPath}"); + } + + if (!string.IsNullOrEmpty(Configuration)) + { + msbuildArgs.Add($"/p:Configuration={Configuration}"); + } + + if (!string.IsNullOrEmpty(VersionSuffix)) + { + msbuildArgs.Add($"/p:VersionSuffix={VersionSuffix}"); + } + + msbuildArgs.AddRange(ExtraMSBuildArguments); + + return new MSBuildForwardingApp(msbuildArgs).Execute(); + } + + /// + /// Ensures that the project has been restored for the specified runtime. + /// + private int EnsureRestored() + { + int result = 0; + + if (!string.IsNullOrEmpty(Runtime)) + { + result = Restore3Command.Run(new[] { $"/p:RuntimeIdentifiers={Runtime}" }); + } + + return result; + } + } +} diff --git a/test/Microsoft.DotNet.Tools.Tests.Utilities/Commands/Publish3Command.cs b/test/Microsoft.DotNet.Tools.Tests.Utilities/Commands/Publish3Command.cs index 1d0aa6548..7b0f56d06 100644 --- a/test/Microsoft.DotNet.Tools.Tests.Utilities/Commands/Publish3Command.cs +++ b/test/Microsoft.DotNet.Tools.Tests.Utilities/Commands/Publish3Command.cs @@ -7,21 +7,46 @@ namespace Microsoft.DotNet.Tools.Test.Utilities { public sealed class Publish3Command : TestCommand { + private string _framework; + private string _runtime; + public Publish3Command() : base("dotnet") { } + public Publish3Command WithFramework(string framework) + { + _framework = framework; + return this; + } + + public Publish3Command WithRuntime(string runtime) + { + _runtime = runtime; + return this; + } + public override CommandResult Execute(string args = "") { - args = $"publish3 {args}"; + args = $"publish3 {args} {BuildArgs()}"; return base.Execute(args); } public override CommandResult ExecuteWithCapturedOutput(string args = "") { - args = $"publish3 {args}"; + args = $"publish3 {args} {BuildArgs()}"; return base.ExecuteWithCapturedOutput(args); } + + private string BuildArgs() + { + return string.Join(" ", + FrameworkOption, + RuntimeOption); + } + + private string FrameworkOption => string.IsNullOrEmpty(_framework) ? "" : $"-f {_framework}"; + private string RuntimeOption => string.IsNullOrEmpty(_runtime) ? "" : $"-r {_runtime}"; } } diff --git a/test/dotnet-publish3.Tests/GivenDotnetPublish3PublishesProjects.cs b/test/dotnet-publish3.Tests/GivenDotnetPublish3PublishesProjects.cs index 4d6a14b3f..eb7905210 100644 --- a/test/dotnet-publish3.Tests/GivenDotnetPublish3PublishesProjects.cs +++ b/test/dotnet-publish3.Tests/GivenDotnetPublish3PublishesProjects.cs @@ -4,6 +4,8 @@ using System; using System.IO; using FluentAssertions; +using Microsoft.DotNet.Cli.Utils; +using Microsoft.DotNet.PlatformAbstractions; using Microsoft.DotNet.Tools.Test.Utilities; using Xunit; @@ -42,5 +44,34 @@ namespace Microsoft.DotNet.Cli.Publish3.Tests .And .HaveStdOutContaining("Hello World"); } + + [Fact] + public void ItPublishesARunnableSelfContainedApp() + { + var testAppName = "MSBuildTestAppPackageRefs"; + var testInstance = TestAssetsManager + .CreateTestInstance(testAppName); + + var testProjectDirectory = testInstance.TestRoot; + var rid = RuntimeEnvironment.GetRuntimeIdentifier(); + + new Publish3Command() + .WithFramework("netcoreapp1.0") + .WithRuntime(rid) + .WithWorkingDirectory(testProjectDirectory) + .Execute() + .Should() + .Pass(); + + var configuration = Environment.GetEnvironmentVariable("CONFIGURATION") ?? "Debug"; + var outputProgram = Path.Combine(testProjectDirectory, "bin", configuration, "netcoreapp1.0", rid, "publish", $"{testAppName}{Constants.ExeSuffix}"); + + new TestCommand(outputProgram) + .ExecuteWithCapturedOutput() + .Should() + .Pass() + .And + .HaveStdOutContaining("Hello World"); + } } }