Adding pre/post publish scripts

Fixes #742
This commit is contained in:
moozzyk 2016-01-11 13:40:47 -08:00
parent 02827620f8
commit 0e4719ee95
8 changed files with 94 additions and 27 deletions

View file

@ -9,5 +9,7 @@ namespace Microsoft.DotNet.Cli.Utils
{ {
public const string PreCompile = "precompile"; public const string PreCompile = "precompile";
public const string PostCompile = "postcompile"; public const string PostCompile = "postcompile";
public const string PrePublish = "prepublish";
public const string PostPublish = "postpublish";
} }
} }

View file

@ -11,6 +11,7 @@ using System.IO;
using System.Linq; using System.Linq;
using Microsoft.Extensions.PlatformAbstractions; using Microsoft.Extensions.PlatformAbstractions;
using Microsoft.DotNet.Tools.Common; using Microsoft.DotNet.Tools.Common;
using Microsoft.DotNet.ProjectModel.Utilities;
namespace Microsoft.DotNet.Tools.Publish namespace Microsoft.DotNet.Tools.Publish
{ {
@ -56,6 +57,7 @@ namespace Microsoft.DotNet.Tools.Publish
{ {
NumberOfPublishedProjects = 0; NumberOfPublishedProjects = 0;
NumberOfProjects = 0; NumberOfProjects = 0;
foreach (var project in ProjectContexts) foreach (var project in ProjectContexts)
{ {
if (PublishProjectContext(project, OutputPath, Configuration, NativeSubdirectories)) if (PublishProjectContext(project, OutputPath, Configuration, NativeSubdirectories))
@ -91,6 +93,17 @@ namespace Microsoft.DotNet.Tools.Publish
context.RuntimeIdentifier); context.RuntimeIdentifier);
} }
var contextVariables = new Dictionary<string, string>
{
{ "publish:ProjectPath", context.ProjectDirectory },
{ "publish:Configuration", configuration },
{ "publish:OutputPath", outputPath },
{ "publish:Framework", context.TargetFramework.Framework },
{ "publish:Runtime", context.RuntimeIdentifier },
};
RunScripts(context, ScriptNames.PrePublish, contextVariables);
if (!Directory.Exists(outputPath)) if (!Directory.Exists(outputPath))
{ {
Directory.CreateDirectory(outputPath); Directory.CreateDirectory(outputPath);
@ -138,7 +151,10 @@ namespace Microsoft.DotNet.Tools.Publish
PublishHost(context, outputPath); PublishHost(context, outputPath);
} }
RunScripts(context, ScriptNames.PostPublish, contextVariables);
Reporter.Output.WriteLine($"Published to {outputPath}".Green().Bold()); Reporter.Output.WriteLine($"Published to {outputPath}".Green().Bold());
return true; return true;
} }
@ -298,5 +314,16 @@ namespace Microsoft.DotNet.Tools.Publish
} }
} }
} }
private static void RunScripts(ProjectContext context, string name, Dictionary<string, string> contextVariables)
{
foreach (var script in context.ProjectFile.Scripts.GetOrEmpty(name))
{
ScriptExecutor.CreateCommandForScript(context.ProjectFile, script, contextVariables)
.ForwardStdErr()
.ForwardStdOut()
.Execute();
}
}
} }
} }

View file

@ -1,15 +1,12 @@
// Copyright (c) .NET Foundation and contributors. All rights reserved. // 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. // Licensed under the MIT license. See LICENSE file in the project root for full license information.
using System;
using System.IO;
using System.Runtime.InteropServices;
using Microsoft.DotNet.Tools.Test.Utilities;
using Xunit;
using System.Linq;
using System.Collections.Generic; using System.Collections.Generic;
using Microsoft.DotNet.ProjectModel; using System.IO;
using System.Text.RegularExpressions;
using Microsoft.DotNet.Tools.Test.Utilities;
using Microsoft.Extensions.PlatformAbstractions; using Microsoft.Extensions.PlatformAbstractions;
using Xunit;
namespace Microsoft.DotNet.Tools.Publish.Tests namespace Microsoft.DotNet.Tools.Publish.Tests
{ {
@ -89,7 +86,7 @@ namespace Microsoft.DotNet.Tools.Publish.Tests
publishCommand.Execute().Should().Pass(); publishCommand.Execute().Should().Pass();
// make sure that the output dir has the content files // make sure that the output dir has the content files
publishCommand.GetOutputDirectory().Should().HaveFile("testcontentfile.txt"); publishCommand.GetOutputDirectory().Should().HaveFile("testcontentfile.txt");
} }
[Fact] [Fact]
@ -116,7 +113,7 @@ namespace Microsoft.DotNet.Tools.Publish.Tests
var root = Temp.CreateDirectory(); var root = Temp.CreateDirectory();
var testLibDir = root.CreateDirectory("TestLibrary"); var testLibDir = root.CreateDirectory("TestLibrary");
//copy projects to the temp dir //copy projects to the temp dir
CopyProjectToTempDir(Path.Combine(_testProjectsRoot, "TestLibrary"), testLibDir); CopyProjectToTempDir(Path.Combine(_testProjectsRoot, "TestLibrary"), testLibDir);
RunRestore(testLibDir.Path); RunRestore(testLibDir.Path);
@ -148,6 +145,31 @@ namespace Microsoft.DotNet.Tools.Publish.Tests
publishCommand.Execute().Should().Fail(); publishCommand.Execute().Should().Fail();
} }
[Fact]
public void PublishScriptsRun()
{
// create unique directories in the 'temp' folder
var root = Temp.CreateDirectory();
var testAppDir = root.CreateDirectory("TestApp");
var testLibDir = root.CreateDirectory("TestLibrary");
//copy projects to the temp dir
CopyProjectToTempDir(Path.Combine(_testProjectsRoot, "TestApp"), testAppDir);
CopyProjectToTempDir(Path.Combine(_testProjectsRoot, "TestLibrary"), testLibDir);
RunRestore(testAppDir.Path);
RunRestore(testLibDir.Path);
// run publish
var testProject = GetProjectPath(testAppDir);
var publishCommand = new PublishCommand(testProject);
var result = publishCommand.ExecuteWithCapturedOutput();
result.Should().StdOutMatchPattern("\nprepublish_output( \\?[^%]+\\?){5}.+\npostpublish_output( \\?[^%]+\\?){5}", RegexOptions.Singleline);
result.Should().Pass();
}
private void CopyProjectToTempDir(string projectDir, TempDirectory tempDir) private void CopyProjectToTempDir(string projectDir, TempDirectory tempDir)
{ {
// copy all the files to temp dir // copy all the files to temp dir
@ -174,4 +196,4 @@ namespace Microsoft.DotNet.Tools.Publish.Tests
restoreCommand.Execute($"--quiet {args}").Should().Pass(); restoreCommand.Execute($"--quiet {args}").Should().Pass();
} }
} }
} }

View file

@ -1,9 +1,10 @@
{ {
"version": "1.0.0-*", "version": "1.0.0-*",
"dependencies": { "dependencies": {
"NETStandard.Library": "1.0.0-rc2-23704", "NETStandard.Library": "1.0.0-rc2-23704",
"Microsoft.NETCore.TestHost" : "1.0.0-*", "Microsoft.NETCore.TestHost": "1.0.0-*",
"System.Text.RegularExpressions": "4.0.11-*",
"xunit": "2.1.0", "xunit": "2.1.0",
"xunit.console.netcore": "1.0.2-prerelease-00101", "xunit.console.netcore": "1.0.2-prerelease-00101",

View file

@ -1,13 +1,11 @@
// Copyright (c) .NET Foundation and contributors. All rights reserved. // 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. // Licensed under the MIT license. See LICENSE file in the project root for full license information.
using System;
using System.Text.RegularExpressions;
using FluentAssertions; using FluentAssertions;
using FluentAssertions.Execution; using FluentAssertions.Execution;
using Microsoft.DotNet.Cli.Utils; using Microsoft.DotNet.Cli.Utils;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
namespace Microsoft.DotNet.Tools.Test.Utilities namespace Microsoft.DotNet.Tools.Test.Utilities
{ {
@ -28,7 +26,7 @@ namespace Microsoft.DotNet.Tools.Test.Utilities
} }
public AndConstraint<CommandResultAssertions> Pass() public AndConstraint<CommandResultAssertions> Pass()
{ {
Execute.Assertion.ForCondition(_commandResult.ExitCode == 0) Execute.Assertion.ForCondition(_commandResult.ExitCode == 0)
.FailWith("Expected command to pass but it exited with {0}.", _commandResult.ExitCode); .FailWith("Expected command to pass but it exited with {0}.", _commandResult.ExitCode);
return new AndConstraint<CommandResultAssertions>(this); return new AndConstraint<CommandResultAssertions>(this);
@ -42,7 +40,7 @@ namespace Microsoft.DotNet.Tools.Test.Utilities
} }
public AndConstraint<CommandResultAssertions> HaveStdOut() public AndConstraint<CommandResultAssertions> HaveStdOut()
{ {
Execute.Assertion.ForCondition(!string.IsNullOrEmpty(_commandResult.StdOut)) Execute.Assertion.ForCondition(!string.IsNullOrEmpty(_commandResult.StdOut))
.FailWith("Command did not output anything to stdout"); .FailWith("Command did not output anything to stdout");
return new AndConstraint<CommandResultAssertions>(this); return new AndConstraint<CommandResultAssertions>(this);
@ -55,6 +53,13 @@ namespace Microsoft.DotNet.Tools.Test.Utilities
return new AndConstraint<CommandResultAssertions>(this); return new AndConstraint<CommandResultAssertions>(this);
} }
public AndConstraint<CommandResultAssertions> StdOutMatchPattern(string pattern, RegexOptions options = RegexOptions.None)
{
Execute.Assertion.ForCondition(Regex.Match(_commandResult.StdOut, pattern, options).Success)
.FailWith($"Matching the command output failed. Pattern: {pattern}{Environment.NewLine} input: {_commandResult.StdOut}");
return new AndConstraint<CommandResultAssertions>(this);
}
public AndConstraint<CommandResultAssertions> HaveStdErr() public AndConstraint<CommandResultAssertions> HaveStdErr()
{ {
Execute.Assertion.ForCondition(!string.IsNullOrEmpty(_commandResult.StdErr)) Execute.Assertion.ForCondition(!string.IsNullOrEmpty(_commandResult.StdErr))

View file

@ -31,17 +31,21 @@ namespace Microsoft.DotNet.Tools.Test.Utilities
_framework = framework; _framework = framework;
_runtime = runtime; _runtime = runtime;
_output = output; _output = output;
_config = config; _config = config;
} }
public override CommandResult Execute(string args="") public override CommandResult Execute(string args="")
{ {
args = $"publish {BuildArgs()} {args}"; args = $"publish {BuildArgs()} {args}";
return base.Execute(args); return base.Execute(args);
} }
public override CommandResult ExecuteWithCapturedOutput(string args = "")
{
args = $"publish {BuildArgs()} {args}";
return base.ExecuteWithCapturedOutput(args);
}
public string ProjectName public string ProjectName
{ {
get get
@ -52,9 +56,9 @@ namespace Microsoft.DotNet.Tools.Test.Utilities
private string BuildRelativeOutputPath() private string BuildRelativeOutputPath()
{ {
// lets try to build an approximate output path // lets try to build an approximate output path
string config = string.IsNullOrEmpty(_config) ? "Debug" : _config; string config = string.IsNullOrEmpty(_config) ? "Debug" : _config;
string framework = string.IsNullOrEmpty(_framework) ? string framework = string.IsNullOrEmpty(_framework) ?
_project.GetTargetFrameworks().First().FrameworkName.GetShortFolderName() : _framework; _project.GetTargetFrameworks().First().FrameworkName.GetShortFolderName() : _framework;
string runtime = string.IsNullOrEmpty(_runtime) ? PlatformServices.Default.Runtime.GetLegacyRestoreRuntimeIdentifier() : _runtime; string runtime = string.IsNullOrEmpty(_runtime) ? PlatformServices.Default.Runtime.GetLegacyRestoreRuntimeIdentifier() : _runtime;
string output = Path.Combine("bin", config, framework, runtime); string output = Path.Combine("bin", config, framework, runtime);

View file

@ -10,11 +10,12 @@
"System.IO.FileSystem": "4.0.1-*", "System.IO.FileSystem": "4.0.1-*",
"System.IO": "4.0.11-*", "System.IO": "4.0.11-*",
"System.Runtime.InteropServices": "4.0.21-*", "System.Runtime.InteropServices": "4.0.21-*",
"System.Text.RegularExpressions": "4.0.11-*",
"FluentAssertions": "4.0.0", "FluentAssertions": "4.0.0",
"Microsoft.DotNet.Cli.Utils": { "target": "project" } "Microsoft.DotNet.Cli.Utils": { "target": "project" }
}, },
"frameworks": { "frameworks": {
"dnxcore50": { } "dnxcore50": { }

View file

@ -15,5 +15,10 @@
"frameworks": { "frameworks": {
"dnxcore50": { } "dnxcore50": { }
},
"scripts": {
"prepublish" : ["echo prepublish_output ?%publish:ProjectPath%? ?%publish:Configuration%? ?%publish:OutputPath%? ?%publish:Framework%? ?%publish:Runtime%?"],
"postpublish" : ["echo postpublish_output ?%publish:ProjectPath%? ?%publish:Configuration%? ?%publish:OutputPath%? ?%publish:Framework%? ?%publish:Runtime%?"]
} }
} }