mirror of
https://github.com/ckaczor/sqltoolsservice.git
synced 2026-01-13 17:23:02 -05:00
Build scripts to create publish folders and archive packages
This commit is contained in:
75
BUILD.md
Normal file
75
BUILD.md
Normal file
@@ -0,0 +1,75 @@
|
||||
# Usage
|
||||
|
||||
Run `build.(ps1|sh)` with the desired set of arguments (see below for options).
|
||||
The build script itself is `build.cake`, written in C# using the Cake build automation system.
|
||||
All build related activites should be encapsulated in this file for cross-platform access.
|
||||
|
||||
# Arguments
|
||||
|
||||
## Primary
|
||||
|
||||
`-target=TargetName`: The name of the build task/target to execute (see below for listing and details).
|
||||
Defaults to `Default`.
|
||||
|
||||
`-configuration=(Release|Debug)`: The configuration to build.
|
||||
Defaults to `Release`.
|
||||
|
||||
## Extra
|
||||
|
||||
`-test-configuration=(Release|Debug)`: The configuration to use for the unit tests.
|
||||
Defaults to `Debug`.
|
||||
|
||||
`-install-path=Path`: Path used for the **Install** target.
|
||||
Defaults to `(%USERPROFILE%|$HOME)/.sqltoolsservice/local`
|
||||
|
||||
`-archive`: Enable the generation of publishable archives after a build.
|
||||
|
||||
# Targets
|
||||
|
||||
**Default**: Alias for Local.
|
||||
|
||||
**Local**: Full build including testing for the machine-local runtime.
|
||||
|
||||
**All**: Same as local, but targeting all runtimes selected by `PopulateRuntimes` in `build.cake`.
|
||||
Currently configured to also build for a 32-bit Windows runtime on Windows machines.
|
||||
No additional runtimes are currently selected on non-Windows machines.
|
||||
|
||||
**Quick**: Local build which skips all testing.
|
||||
|
||||
**Install**: Same as quick, but installs the generated binaries into `install-path`.
|
||||
|
||||
**SetPackageVersions**: Updates the dependency versions found within `project.json` files using information from `depversion.json`.
|
||||
Used for maintainence within the project, not needed for end-users. More information below.
|
||||
|
||||
# Configuration files
|
||||
|
||||
## build.json
|
||||
|
||||
A number of build-related options, including folder names for different entities. Interesting options:
|
||||
|
||||
**DotNetInstallScriptURL**: The URL where the .NET SDK install script is located.
|
||||
Can be used to pin to a specific script version, if a breaking change occurs.
|
||||
|
||||
**"DotNetChannel"**: The .NET SDK channel used for retreiving the tools.
|
||||
|
||||
**"DotNetVersion"**: The .NET SDK version used for the build. Can be used to pin to a specific version.
|
||||
Using the string `Latest` will retrieve the latest version.
|
||||
|
||||
## depversion.json
|
||||
|
||||
A listing of all dependencies (and their desired versions) used by `project.json` files throughout the project.
|
||||
Allows for quick and automatic updates to the dependency version numbers using the **SetPackageVersions** target.
|
||||
|
||||
# Artifacts generated
|
||||
|
||||
* Binaries of Microsoft.SqlTools.ServiceLayer and its libraries built for the local machine in `artifacts/publish/Microsoft.SqlTools.ServiceLayer/default/{framework}/`
|
||||
* Scripts to run Microsoft.SqlTools.ServiceLayer at `scripts/SQLTOOLSSERVICE(.Core)(.cmd)`
|
||||
* These scripts are updated for every build and every install.
|
||||
* The scripts point to the installed binary after and install, otherwise just the build folder (reset if a new build occurs without an install).
|
||||
* Binaries of Microsoft.SqlTools.ServiceLayer and its libraries cross-compiled for other runtimes (if selected in **PopulateRuntimes**) `artifacts/publish/Microsoft.SqlTools.ServiceLayer/{runtime}/{framework}/`
|
||||
* Test logs in `artifacts/logs`
|
||||
* Archived binaries in `artifacts/package` (only if `-archive` used on command line)
|
||||
|
||||
# Requirements
|
||||
|
||||
The build system requires Mono to be installed on non-Windows machines as Cake is not built using .NET Core (yet).
|
||||
507
build.cake
Normal file
507
build.cake
Normal file
@@ -0,0 +1,507 @@
|
||||
#addin "Newtonsoft.Json"
|
||||
|
||||
#load "scripts/runhelpers.cake"
|
||||
#load "scripts/archiving.cake"
|
||||
#load "scripts/artifacts.cake"
|
||||
|
||||
using System.ComponentModel;
|
||||
using System.Net;
|
||||
using Newtonsoft.Json;
|
||||
using Newtonsoft.Json.Linq;
|
||||
|
||||
// Basic arguments
|
||||
var target = Argument("target", "Default");
|
||||
var configuration = Argument("configuration", "Release");
|
||||
// Optional arguments
|
||||
var testConfiguration = Argument("test-configuration", "Debug");
|
||||
var installFolder = Argument("install-path", System.IO.Path.Combine(Environment.GetEnvironmentVariable(IsRunningOnWindows() ? "USERPROFILE" : "HOME"),
|
||||
".sqltoolsservice", "local"));
|
||||
var requireArchive = HasArgument("archive");
|
||||
|
||||
// Working directory
|
||||
var workingDirectory = System.IO.Directory.GetCurrentDirectory();
|
||||
|
||||
// System specific shell configuration
|
||||
var shell = IsRunningOnWindows() ? "powershell" : "bash";
|
||||
var shellArgument = IsRunningOnWindows() ? "-NoProfile /Command" : "-C";
|
||||
var shellExtension = IsRunningOnWindows() ? "ps1" : "sh";
|
||||
|
||||
/// <summary>
|
||||
/// Class representing build.json
|
||||
/// </summary>
|
||||
public class BuildPlan
|
||||
{
|
||||
public IDictionary<string, string[]> TestProjects { get; set; }
|
||||
public string BuildToolsFolder { get; set; }
|
||||
public string ArtifactsFolder { get; set; }
|
||||
public bool UseSystemDotNetPath { get; set; }
|
||||
public string DotNetFolder { get; set; }
|
||||
public string DotNetInstallScriptURL { get; set; }
|
||||
public string DotNetChannel { get; set; }
|
||||
public string DotNetVersion { get; set; }
|
||||
public string[] Frameworks { get; set; }
|
||||
public string[] Rids { get; set; }
|
||||
public string MainProject { get; set; }
|
||||
}
|
||||
|
||||
var buildPlan = JsonConvert.DeserializeObject<BuildPlan>(
|
||||
System.IO.File.ReadAllText(System.IO.Path.Combine(workingDirectory, "build.json")));
|
||||
|
||||
// Folders and tools
|
||||
var dotnetFolder = System.IO.Path.Combine(workingDirectory, buildPlan.DotNetFolder);
|
||||
var dotnetcli = buildPlan.UseSystemDotNetPath ? "dotnet" : System.IO.Path.Combine(System.IO.Path.GetFullPath(dotnetFolder), "dotnet");
|
||||
var toolsFolder = System.IO.Path.Combine(workingDirectory, buildPlan.BuildToolsFolder);
|
||||
|
||||
var sourceFolder = System.IO.Path.Combine(workingDirectory, "src");
|
||||
var testFolder = System.IO.Path.Combine(workingDirectory, "test");
|
||||
|
||||
var artifactFolder = System.IO.Path.Combine(workingDirectory, buildPlan.ArtifactsFolder);
|
||||
var publishFolder = System.IO.Path.Combine(artifactFolder, "publish");
|
||||
var logFolder = System.IO.Path.Combine(artifactFolder, "logs");
|
||||
var packageFolder = System.IO.Path.Combine(artifactFolder, "package");
|
||||
var scriptFolder = System.IO.Path.Combine(artifactFolder, "scripts");
|
||||
|
||||
/// <summary>
|
||||
/// Clean artifacts.
|
||||
/// </summary>
|
||||
Task("Cleanup")
|
||||
.Does(() =>
|
||||
{
|
||||
if (System.IO.Directory.Exists(artifactFolder))
|
||||
{
|
||||
System.IO.Directory.Delete(artifactFolder, true);
|
||||
}
|
||||
System.IO.Directory.CreateDirectory(artifactFolder);
|
||||
System.IO.Directory.CreateDirectory(logFolder);
|
||||
System.IO.Directory.CreateDirectory(packageFolder);
|
||||
System.IO.Directory.CreateDirectory(scriptFolder);
|
||||
});
|
||||
|
||||
/// <summary>
|
||||
/// Pre-build setup tasks.
|
||||
/// </summary>
|
||||
Task("Setup")
|
||||
.IsDependentOn("BuildEnvironment")
|
||||
.IsDependentOn("PopulateRuntimes")
|
||||
.Does(() =>
|
||||
{
|
||||
});
|
||||
|
||||
/// <summary>
|
||||
/// Populate the RIDs for the specific environment.
|
||||
/// Use default RID (+ win7-x86 on Windows) for now.
|
||||
/// </summary>
|
||||
Task("PopulateRuntimes")
|
||||
.IsDependentOn("BuildEnvironment")
|
||||
.Does(() =>
|
||||
{
|
||||
buildPlan.Rids = new string[]
|
||||
{
|
||||
"default", // To allow testing the published artifact
|
||||
"win7-x64",
|
||||
"win7-x86",
|
||||
"ubuntu.14.04-x64",
|
||||
"ubuntu.16.04-x64",
|
||||
"centos.7-x64",
|
||||
"rhel.7.2-x64",
|
||||
"debian.8-x64",
|
||||
"fedora.23-x64",
|
||||
"opensuse.13.2-x64",
|
||||
"osx.10.11-x64"
|
||||
};
|
||||
});
|
||||
|
||||
/// <summary>
|
||||
/// Install/update build environment.
|
||||
/// </summary>
|
||||
Task("BuildEnvironment")
|
||||
.Does(() =>
|
||||
{
|
||||
var installScript = $"dotnet-install.{shellExtension}";
|
||||
System.IO.Directory.CreateDirectory(dotnetFolder);
|
||||
var scriptPath = System.IO.Path.Combine(dotnetFolder, installScript);
|
||||
using (WebClient client = new WebClient())
|
||||
{
|
||||
client.DownloadFile($"{buildPlan.DotNetInstallScriptURL}/{installScript}", scriptPath);
|
||||
}
|
||||
if (!IsRunningOnWindows())
|
||||
{
|
||||
Run("chmod", $"+x '{scriptPath}'");
|
||||
}
|
||||
var installArgs = $"-Channel {buildPlan.DotNetChannel}";
|
||||
if (!String.IsNullOrEmpty(buildPlan.DotNetVersion))
|
||||
{
|
||||
installArgs = $"{installArgs} -Version {buildPlan.DotNetVersion}";
|
||||
}
|
||||
if (!buildPlan.UseSystemDotNetPath)
|
||||
{
|
||||
installArgs = $"{installArgs} -InstallDir {dotnetFolder}";
|
||||
}
|
||||
Run(shell, $"{shellArgument} {scriptPath} {installArgs}");
|
||||
try
|
||||
{
|
||||
Run(dotnetcli, "--info");
|
||||
}
|
||||
catch (Win32Exception)
|
||||
{
|
||||
throw new Exception(".NET CLI binary cannot be found.");
|
||||
}
|
||||
|
||||
System.IO.Directory.CreateDirectory(toolsFolder);
|
||||
|
||||
var nugetPath = Environment.GetEnvironmentVariable("NUGET_EXE");
|
||||
var arguments = $"install xunit.runner.console -ExcludeVersion -NoCache -Prerelease -OutputDirectory \"{toolsFolder}\"";
|
||||
if (IsRunningOnWindows())
|
||||
{
|
||||
Run(nugetPath, arguments);
|
||||
}
|
||||
else
|
||||
{
|
||||
Run("mono", $"\"{nugetPath}\" {arguments}");
|
||||
}
|
||||
});
|
||||
|
||||
/// <summary>
|
||||
/// Restore required NuGet packages.
|
||||
/// </summary>
|
||||
Task("Restore")
|
||||
.IsDependentOn("Setup")
|
||||
.Does(() =>
|
||||
{
|
||||
RunRestore(dotnetcli, "restore", sourceFolder)
|
||||
.ExceptionOnError("Failed to restore projects under source code folder.");
|
||||
RunRestore(dotnetcli, "restore --infer-runtimes", testFolder)
|
||||
.ExceptionOnError("Failed to restore projects under test code folder.");
|
||||
});
|
||||
|
||||
/// <summary>
|
||||
/// Build Test projects.
|
||||
/// </summary>
|
||||
Task("BuildTest")
|
||||
.IsDependentOn("Setup")
|
||||
.IsDependentOn("Restore")
|
||||
.Does(() =>
|
||||
{
|
||||
foreach (var pair in buildPlan.TestProjects)
|
||||
{
|
||||
foreach (var framework in pair.Value)
|
||||
{
|
||||
var project = pair.Key;
|
||||
var projectFolder = System.IO.Path.Combine(testFolder, project);
|
||||
var runLog = new List<string>();
|
||||
Run(dotnetcli, $"build --framework {framework} --configuration {testConfiguration} \"{projectFolder}\"",
|
||||
new RunOptions
|
||||
{
|
||||
StandardOutputListing = runLog
|
||||
})
|
||||
.ExceptionOnError($"Building test {project} failed for {framework}.");
|
||||
System.IO.File.WriteAllLines(System.IO.Path.Combine(logFolder, $"{project}-{framework}-build.log"), runLog.ToArray());
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
/// <summary>
|
||||
/// Run all tests for .NET Desktop and .NET Core
|
||||
/// </summary>
|
||||
Task("TestAll")
|
||||
.IsDependentOn("Test")
|
||||
.IsDependentOn("TestCore")
|
||||
.Does(() =>{});
|
||||
|
||||
/// <summary>
|
||||
/// Run all tests for Travis CI .NET Desktop and .NET Core
|
||||
/// </summary>
|
||||
Task("TravisTestAll")
|
||||
.IsDependentOn("Cleanup")
|
||||
.IsDependentOn("TestAll")
|
||||
.Does(() =>{});
|
||||
|
||||
/// <summary>
|
||||
/// Run tests for .NET Core (using .NET CLI).
|
||||
/// </summary>
|
||||
Task("TestCore")
|
||||
.IsDependentOn("Setup")
|
||||
.IsDependentOn("Restore")
|
||||
.Does(() =>
|
||||
{
|
||||
var testProjects = buildPlan.TestProjects
|
||||
.Where(pair => pair.Value.Any(framework => framework.Contains("netcoreapp")))
|
||||
.Select(pair => pair.Key)
|
||||
.ToList();
|
||||
|
||||
foreach (var testProject in testProjects)
|
||||
{
|
||||
var logFile = System.IO.Path.Combine(logFolder, $"{testProject}-core-result.xml");
|
||||
var testWorkingDir = System.IO.Path.Combine(testFolder, testProject);
|
||||
Run(dotnetcli, $"test -f netcoreapp1.0 -xml \"{logFile}\" -notrait category=failing", testWorkingDir)
|
||||
.ExceptionOnError($"Test {testProject} failed for .NET Core.");
|
||||
}
|
||||
});
|
||||
|
||||
/// <summary>
|
||||
/// Run tests for other frameworks (using XUnit2).
|
||||
/// </summary>
|
||||
Task("Test")
|
||||
.IsDependentOn("Setup")
|
||||
.IsDependentOn("BuildTest")
|
||||
.Does(() =>
|
||||
{
|
||||
foreach (var pair in buildPlan.TestProjects)
|
||||
{
|
||||
foreach (var framework in pair.Value)
|
||||
{
|
||||
// Testing against core happens in TestCore
|
||||
if (framework.Contains("netcoreapp"))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
var project = pair.Key;
|
||||
var frameworkFolder = System.IO.Path.Combine(testFolder, project, "bin", testConfiguration, framework);
|
||||
var runtime = System.IO.Directory.GetDirectories(frameworkFolder).First();
|
||||
var instanceFolder = System.IO.Path.Combine(frameworkFolder, runtime);
|
||||
|
||||
// Copy xunit executable to test folder to solve path errors
|
||||
var xunitToolsFolder = System.IO.Path.Combine(toolsFolder, "xunit.runner.console", "tools");
|
||||
var xunitInstancePath = System.IO.Path.Combine(instanceFolder, "xunit.console.exe");
|
||||
System.IO.File.Copy(System.IO.Path.Combine(xunitToolsFolder, "xunit.console.exe"), xunitInstancePath, true);
|
||||
System.IO.File.Copy(System.IO.Path.Combine(xunitToolsFolder, "xunit.runner.utility.desktop.dll"), System.IO.Path.Combine(instanceFolder, "xunit.runner.utility.desktop.dll"), true);
|
||||
var targetPath = System.IO.Path.Combine(instanceFolder, $"{project}.dll");
|
||||
var logFile = System.IO.Path.Combine(logFolder, $"{project}-{framework}-result.xml");
|
||||
var arguments = $"\"{targetPath}\" -parallel none -xml \"{logFile}\" -notrait category=failing";
|
||||
if (IsRunningOnWindows())
|
||||
{
|
||||
Run(xunitInstancePath, arguments, instanceFolder)
|
||||
.ExceptionOnError($"Test {project} failed for {framework}");
|
||||
}
|
||||
else
|
||||
{
|
||||
Run("mono", $"\"{xunitInstancePath}\" {arguments}", instanceFolder)
|
||||
.ExceptionOnError($"Test {project} failed for {framework}");
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
/// <summary>
|
||||
/// Build, publish and package artifacts.
|
||||
/// Targets all RIDs specified in build.json unless restricted by RestrictToLocalRuntime.
|
||||
/// No dependencies on other tasks to support quick builds.
|
||||
/// </summary>
|
||||
Task("OnlyPublish")
|
||||
.IsDependentOn("Setup")
|
||||
.Does(() =>
|
||||
{
|
||||
var project = buildPlan.MainProject;
|
||||
var projectFolder = System.IO.Path.Combine(sourceFolder, project);
|
||||
foreach (var framework in buildPlan.Frameworks)
|
||||
{
|
||||
foreach (var runtime in buildPlan.Rids)
|
||||
{
|
||||
var outputFolder = System.IO.Path.Combine(publishFolder, project, runtime, framework);
|
||||
var publishArguments = "publish";
|
||||
if (!runtime.Equals("default"))
|
||||
{
|
||||
publishArguments = $"{publishArguments} --runtime {runtime}";
|
||||
}
|
||||
publishArguments = $"{publishArguments} --framework {framework} --configuration {configuration}";
|
||||
publishArguments = $"{publishArguments} --output \"{outputFolder}\" \"{projectFolder}\"";
|
||||
Run(dotnetcli, publishArguments)
|
||||
.ExceptionOnError($"Failed to publish {project} / {framework}");
|
||||
|
||||
if (requireArchive)
|
||||
{
|
||||
Package(runtime, framework, outputFolder, packageFolder, buildPlan.MainProject.ToLower());
|
||||
}
|
||||
}
|
||||
}
|
||||
CreateRunScript(System.IO.Path.Combine(publishFolder, project, "default"), scriptFolder);
|
||||
});
|
||||
|
||||
/// <summary>
|
||||
/// Alias for OnlyPublish.
|
||||
/// Targets all RIDs as specified in build.json.
|
||||
/// </summary>
|
||||
Task("AllPublish")
|
||||
.IsDependentOn("Restore")
|
||||
.IsDependentOn("OnlyPublish")
|
||||
.Does(() =>
|
||||
{
|
||||
});
|
||||
|
||||
/// <summary>
|
||||
/// Restrict the RIDs for the local default.
|
||||
/// </summary>
|
||||
Task("RestrictToLocalRuntime")
|
||||
.IsDependentOn("Setup")
|
||||
.Does(() =>
|
||||
{
|
||||
buildPlan.Rids = new string[] {"default"};
|
||||
});
|
||||
|
||||
/// <summary>
|
||||
/// Alias for OnlyPublish.
|
||||
/// Restricts publishing to local RID.
|
||||
/// </summary>
|
||||
Task("LocalPublish")
|
||||
.IsDependentOn("Restore")
|
||||
.IsDependentOn("RestrictToLocalRuntime")
|
||||
.IsDependentOn("OnlyPublish")
|
||||
.Does(() =>
|
||||
{
|
||||
});
|
||||
|
||||
/// <summary>
|
||||
/// Test the published binaries if they start up without errors.
|
||||
/// Uses builds corresponding to local RID.
|
||||
/// </summary>
|
||||
Task("TestPublished")
|
||||
.IsDependentOn("Setup")
|
||||
.Does(() =>
|
||||
{
|
||||
var project = buildPlan.MainProject;
|
||||
var projectFolder = System.IO.Path.Combine(sourceFolder, project);
|
||||
var scriptsToTest = new string[] {"SQLTOOLSSERVICE.Core"};//TODO
|
||||
foreach (var script in scriptsToTest)
|
||||
{
|
||||
var scriptPath = System.IO.Path.Combine(scriptFolder, script);
|
||||
var didNotExitWithError = Run($"{shell}", $"{shellArgument} \"{scriptPath}\" -s \"{projectFolder}\" --stdio",
|
||||
new RunOptions
|
||||
{
|
||||
TimeOut = 10000
|
||||
})
|
||||
.DidTimeOut;
|
||||
if (!didNotExitWithError)
|
||||
{
|
||||
throw new Exception($"Failed to run {script}");
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
/// <summary>
|
||||
/// Clean install path.
|
||||
/// </summary>
|
||||
Task("CleanupInstall")
|
||||
.Does(() =>
|
||||
{
|
||||
if (System.IO.Directory.Exists(installFolder))
|
||||
{
|
||||
System.IO.Directory.Delete(installFolder, true);
|
||||
}
|
||||
System.IO.Directory.CreateDirectory(installFolder);
|
||||
});
|
||||
|
||||
/// <summary>
|
||||
/// Quick build.
|
||||
/// </summary>
|
||||
Task("Quick")
|
||||
.IsDependentOn("Cleanup")
|
||||
.IsDependentOn("LocalPublish")
|
||||
.Does(() =>
|
||||
{
|
||||
});
|
||||
|
||||
/// <summary>
|
||||
/// Quick build + install.
|
||||
/// </summary>
|
||||
Task("Install")
|
||||
.IsDependentOn("Cleanup")
|
||||
.IsDependentOn("LocalPublish")
|
||||
.IsDependentOn("CleanupInstall")
|
||||
.Does(() =>
|
||||
{
|
||||
var project = buildPlan.MainProject;
|
||||
foreach (var framework in buildPlan.Frameworks)
|
||||
{
|
||||
var outputFolder = System.IO.Path.GetFullPath(System.IO.Path.Combine(publishFolder, project, "default", framework));
|
||||
var targetFolder = System.IO.Path.GetFullPath(System.IO.Path.Combine(installFolder, framework));
|
||||
// Copy all the folders
|
||||
foreach (var directory in System.IO.Directory.GetDirectories(outputFolder, "*", SearchOption.AllDirectories))
|
||||
System.IO.Directory.CreateDirectory(System.IO.Path.Combine(targetFolder, directory.Substring(outputFolder.Length + 1)));
|
||||
//Copy all the files
|
||||
foreach (string file in System.IO.Directory.GetFiles(outputFolder, "*", SearchOption.AllDirectories))
|
||||
System.IO.File.Copy(file, System.IO.Path.Combine(targetFolder, file.Substring(outputFolder.Length + 1)), true);
|
||||
}
|
||||
CreateRunScript(installFolder, scriptFolder);
|
||||
});
|
||||
|
||||
/// <summary>
|
||||
/// Full build targeting all RIDs specified in build.json.
|
||||
/// </summary>
|
||||
Task("All")
|
||||
.IsDependentOn("Cleanup")
|
||||
.IsDependentOn("Restore")
|
||||
.IsDependentOn("TestAll")
|
||||
.IsDependentOn("AllPublish")
|
||||
//.IsDependentOn("TestPublished")
|
||||
.Does(() =>
|
||||
{
|
||||
});
|
||||
|
||||
/// <summary>
|
||||
/// Full build targeting local RID.
|
||||
/// </summary>
|
||||
Task("Local")
|
||||
.IsDependentOn("Cleanup")
|
||||
.IsDependentOn("Restore")
|
||||
.IsDependentOn("TestAll")
|
||||
.IsDependentOn("LocalPublish")
|
||||
// .IsDependentOn("TestPublished")
|
||||
.Does(() =>
|
||||
{
|
||||
});
|
||||
|
||||
/// <summary>
|
||||
/// Build centered around producing the final artifacts for Travis
|
||||
///
|
||||
/// The tests are run as a different task "TestAll"
|
||||
/// </summary>
|
||||
Task("Travis")
|
||||
.IsDependentOn("Cleanup")
|
||||
.IsDependentOn("Restore")
|
||||
.IsDependentOn("AllPublish")
|
||||
// .IsDependentOn("TestPublished")
|
||||
.Does(() =>
|
||||
{
|
||||
});
|
||||
|
||||
/// <summary>
|
||||
/// Update the package versions within project.json files.
|
||||
/// Uses depversion.json file as input.
|
||||
/// </summary>
|
||||
Task("SetPackageVersions")
|
||||
.Does(() =>
|
||||
{
|
||||
var jDepVersion = JObject.Parse(System.IO.File.ReadAllText(System.IO.Path.Combine(workingDirectory, "depversion.json")));
|
||||
var projects = System.IO.Directory.GetFiles(sourceFolder, "project.json", SearchOption.AllDirectories).ToList();
|
||||
projects.AddRange(System.IO.Directory.GetFiles(testFolder, "project.json", SearchOption.AllDirectories));
|
||||
foreach (var project in projects)
|
||||
{
|
||||
var jProject = JObject.Parse(System.IO.File.ReadAllText(project));
|
||||
var dependencies = jProject.SelectTokens("dependencies")
|
||||
.Union(jProject.SelectTokens("frameworks.*.dependencies"))
|
||||
.SelectMany(dependencyToken => dependencyToken.Children<JProperty>());
|
||||
foreach (JProperty dependency in dependencies)
|
||||
{
|
||||
if (jDepVersion[dependency.Name] != null)
|
||||
{
|
||||
dependency.Value = jDepVersion[dependency.Name];
|
||||
}
|
||||
}
|
||||
System.IO.File.WriteAllText(project, JsonConvert.SerializeObject(jProject, Formatting.Indented));
|
||||
}
|
||||
});
|
||||
|
||||
/// <summary>
|
||||
/// Default Task aliases to Local.
|
||||
/// </summary>
|
||||
Task("Default")
|
||||
.IsDependentOn("Local")
|
||||
.Does(() =>
|
||||
{
|
||||
});
|
||||
|
||||
/// <summary>
|
||||
/// Default to Local.
|
||||
/// </summary>
|
||||
RunTarget(target);
|
||||
18
build.json
Normal file
18
build.json
Normal file
@@ -0,0 +1,18 @@
|
||||
{
|
||||
"UseSystemDotNetPath": "true",
|
||||
"DotNetFolder": ".dotnet",
|
||||
"DotNetInstallScriptURL": "https://raw.githubusercontent.com/dotnet/cli/rel/1.0.0-preview2/scripts/obtain",
|
||||
"DotNetChannel": "preview",
|
||||
"DotNetVersion": "1.0.0-preview2-003121",
|
||||
"BuildToolsFolder": ".tools",
|
||||
"ArtifactsFolder": "artifacts",
|
||||
"TestProjects": {
|
||||
"Microsoft.SqlTools.ServiceLayer.Test": [
|
||||
"netcoreapp1.0"
|
||||
]
|
||||
},
|
||||
"Frameworks": [
|
||||
"netcoreapp1.0"
|
||||
],
|
||||
"MainProject": "Microsoft.SqlTools.ServiceLayer"
|
||||
}
|
||||
3
build.ps1
Normal file
3
build.ps1
Normal file
@@ -0,0 +1,3 @@
|
||||
$Env:SQLTOOLSSERVICE_PACKAGE_OSNAME = "win-x64"
|
||||
.\scripts\cake-bootstrap.ps1 -experimental @args
|
||||
exit $LASTEXITCODE
|
||||
12
build.sh
Normal file
12
build.sh
Normal file
@@ -0,0 +1,12 @@
|
||||
#!/bin/bash
|
||||
# Handle to many files on osx
|
||||
if [ "$TRAVIS_OS_NAME" == "osx" ] || [ `uname` == "Darwin" ]; then
|
||||
ulimit -n 4096
|
||||
fi
|
||||
|
||||
if [ "$TRAVIS_OS_NAME" == "osx" ] || [ `uname` == "Darwin" ]; then
|
||||
export SQLTOOLSSERVICE_PACKAGE_OSNAME=osx-x64
|
||||
else
|
||||
export SQLTOOLSSERVICE_PACKAGE_OSNAME=linux-x64
|
||||
fi
|
||||
bash ./scripts/cake-bootstrap.sh "$@"
|
||||
104
scripts/archiving.cake
Normal file
104
scripts/archiving.cake
Normal file
@@ -0,0 +1,104 @@
|
||||
#load "runhelpers.cake"
|
||||
|
||||
using System.IO.Compression;
|
||||
using System.Text.RegularExpressions;
|
||||
|
||||
/// <summary>
|
||||
/// Generate the build identifier based on the RID and framework identifier.
|
||||
/// Special rules when running on Travis (for publishing purposes).
|
||||
/// </summary>
|
||||
/// <param name="runtime">The RID</param>
|
||||
/// <param name="framework">The framework identifier</param>
|
||||
/// <returns>The designated build identifier</returns>
|
||||
string GetBuildIdentifier(string runtime, string framework)
|
||||
{
|
||||
var runtimeShort = "";
|
||||
// Default RID uses package name set in build script
|
||||
if (runtime.Equals("default"))
|
||||
{
|
||||
runtimeShort = Environment.GetEnvironmentVariable("SQLTOOLSSERVICE_PACKAGE_OSNAME");
|
||||
}
|
||||
else
|
||||
{
|
||||
// Remove version number. Note: because there are separate versions for Ubuntu 14 and 16,
|
||||
// we treat Ubuntu as a special case.
|
||||
if (runtime.StartsWith("ubuntu.14"))
|
||||
{
|
||||
runtimeShort = "ubuntu14-x64";
|
||||
}
|
||||
else if (runtime.StartsWith("ubuntu.16"))
|
||||
{
|
||||
runtimeShort = "ubuntu16-x64";
|
||||
}
|
||||
else
|
||||
{
|
||||
runtimeShort = Regex.Replace(runtime, "(\\d|\\.)*-", "-");
|
||||
}
|
||||
}
|
||||
|
||||
return $"{runtimeShort}-{framework}";
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Generate an archive out of the given published folder.
|
||||
/// Use ZIP for Windows runtimes.
|
||||
/// Use TAR.GZ for non-Windows runtimes.
|
||||
/// Use 7z to generate TAR.GZ on Windows if available.
|
||||
/// </summary>
|
||||
/// <param name="runtime">The RID</param>
|
||||
/// <param name="contentFolder">The folder containing the files to package</param>
|
||||
/// <param name="archiveName">The target archive name (without extension)</param>
|
||||
void DoArchive(string runtime, string contentFolder, string archiveName)
|
||||
{
|
||||
// On all platforms use ZIP for Windows runtimes
|
||||
if (runtime.Contains("win") || (runtime.Equals("default") && IsRunningOnWindows()))
|
||||
{
|
||||
var zipFile = $"{archiveName}.zip";
|
||||
Zip(contentFolder, zipFile);
|
||||
}
|
||||
// On all platforms use TAR.GZ for Unix runtimes
|
||||
else
|
||||
{
|
||||
var tarFile = $"{archiveName}.tar.gz";
|
||||
// Use 7z to create TAR.GZ on Windows
|
||||
if (IsRunningOnWindows())
|
||||
{
|
||||
var tempFile = $"{archiveName}.tar";
|
||||
try
|
||||
{
|
||||
Run("7z", $"a \"{tempFile}\"", contentFolder)
|
||||
.ExceptionOnError($"Tar-ing failed for {contentFolder} {archiveName}");
|
||||
Run("7z", $"a \"{tarFile}\" \"{tempFile}\"", contentFolder)
|
||||
.ExceptionOnError($"Compression failed for {contentFolder} {archiveName}");
|
||||
System.IO.File.Delete(tempFile);
|
||||
}
|
||||
catch(Win32Exception)
|
||||
{
|
||||
Information("Warning: 7z not available on PATH to pack tar.gz results");
|
||||
}
|
||||
}
|
||||
// Use tar to create TAR.GZ on Unix
|
||||
else
|
||||
{
|
||||
Run("tar", $"czf \"{tarFile}\" .", contentFolder)
|
||||
.ExceptionOnError($"Compression failed for {contentFolder} {archiveName}");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Package a given output folder using a build identifier generated from the RID and framework identifier.
|
||||
/// </summary>
|
||||
/// <param name="runtime">The RID</param>
|
||||
/// <param name="framework">The framework identifier</param>
|
||||
/// <param name="contentFolder">The folder containing the files to package</param>
|
||||
/// <param name="packageFolder">The destination folder for the archive</param>
|
||||
/// <param name="projectName">The project name</param>
|
||||
void Package(string runtime, string framework, string contentFolder, string packageFolder, string projectName)
|
||||
{
|
||||
var buildIdentifier = GetBuildIdentifier(runtime, framework);
|
||||
if (buildIdentifier != null)
|
||||
{
|
||||
DoArchive(runtime, contentFolder, $"{packageFolder}/{projectName}-{buildIdentifier}");
|
||||
}
|
||||
}
|
||||
43
scripts/artifacts.cake
Normal file
43
scripts/artifacts.cake
Normal file
@@ -0,0 +1,43 @@
|
||||
#load "runhelpers.cake"
|
||||
|
||||
/// <summary>
|
||||
/// Generate the scripts which target the SQLTOOLSSERVICE binaries.
|
||||
/// </summary>
|
||||
/// <param name="outputRoot">The root folder where the publised (or installed) binaries are located</param>
|
||||
void CreateRunScript(string outputRoot, string scriptFolder)
|
||||
{
|
||||
if (IsRunningOnWindows())
|
||||
{
|
||||
var coreScript = System.IO.Path.Combine(scriptFolder, "SQLTOOLSSERVICE.Core.cmd");
|
||||
var sqlToolsServicePath = System.IO.Path.Combine(System.IO.Path.GetFullPath(outputRoot), "{0}", "SQLTOOLSSERVICE");
|
||||
var content = new string[] {
|
||||
"SETLOCAL",
|
||||
"",
|
||||
$"\"{sqlToolsServicePath}\" %*"
|
||||
};
|
||||
if (System.IO.File.Exists(coreScript))
|
||||
{
|
||||
System.IO.File.Delete(coreScript);
|
||||
}
|
||||
content[2] = String.Format(content[2], "netcoreapp1.0");
|
||||
System.IO.File.WriteAllLines(coreScript, content);
|
||||
}
|
||||
else
|
||||
{
|
||||
var coreScript = System.IO.Path.Combine(scriptFolder, "SQLTOOLSSERVICE.Core");
|
||||
var sqlToolsServicePath = System.IO.Path.Combine(System.IO.Path.GetFullPath(outputRoot), "{1}", "SQLTOOLSSERVICE");
|
||||
var content = new string[] {
|
||||
"#!/bin/bash",
|
||||
"",
|
||||
$"{{0}} \"{sqlToolsServicePath}{{2}}\" \"$@\""
|
||||
};
|
||||
|
||||
if (System.IO.File.Exists(coreScript))
|
||||
{
|
||||
System.IO.File.Delete(coreScript);
|
||||
}
|
||||
content[2] = String.Format(content[2], "", "netcoreapp1.0", "");
|
||||
System.IO.File.WriteAllLines(coreScript, content);
|
||||
Run("chmod", $"+x \"{coreScript}\"");
|
||||
}
|
||||
}
|
||||
110
scripts/cake-bootstrap.ps1
Normal file
110
scripts/cake-bootstrap.ps1
Normal file
@@ -0,0 +1,110 @@
|
||||
<#
|
||||
|
||||
.SYNOPSIS
|
||||
This is a Powershell script to bootstrap a Cake build.
|
||||
|
||||
.DESCRIPTION
|
||||
This Powershell script will download NuGet if missing, restore NuGet tools (including Cake)
|
||||
and execute your Cake build script with the parameters you provide.
|
||||
|
||||
.PARAMETER Script
|
||||
The build script to execute.
|
||||
.PARAMETER Target
|
||||
The build script target to run.
|
||||
.PARAMETER Configuration
|
||||
The build configuration to use.
|
||||
.PARAMETER Verbosity
|
||||
Specifies the amount of information to be displayed.
|
||||
Tells Cake to use the latest Roslyn release.
|
||||
.PARAMETER WhatIf
|
||||
Performs a dry run of the build script.
|
||||
No tasks will be executed.
|
||||
.PARAMETER Mono
|
||||
Tells Cake to use the Mono scripting engine.
|
||||
|
||||
.LINK
|
||||
http://cakebuild.net
|
||||
|
||||
#>
|
||||
|
||||
[CmdletBinding()]
|
||||
Param(
|
||||
[string]$Script = "build.cake",
|
||||
[ValidateSet("Quiet", "Minimal", "Normal", "Verbose", "Diagnostic")]
|
||||
[string]$Verbosity = "Verbose",
|
||||
[Alias("DryRun","Noop")]
|
||||
[switch]$WhatIf,
|
||||
[switch]$Mono,
|
||||
[switch]$SkipToolPackageRestore,
|
||||
[Parameter(Position=0,Mandatory=$false,ValueFromRemainingArguments=$true)]
|
||||
[string[]]$ScriptArgs
|
||||
)
|
||||
|
||||
Write-Host "Preparing to run build script..."
|
||||
|
||||
$PS_SCRIPT_ROOT = split-path -parent $MyInvocation.MyCommand.Definition;
|
||||
$TOOLS_DIR = Join-Path $PSScriptRoot "..\.tools"
|
||||
$NUGET_EXE = Join-Path $TOOLS_DIR "nuget.exe"
|
||||
$NUGET_URL = "https://dist.nuget.org/win-x86-commandline/v3.3.0/nuget.exe"
|
||||
$CAKE_EXE = Join-Path $TOOLS_DIR "Cake/Cake.exe"
|
||||
$PACKAGES_CONFIG = Join-Path $PS_SCRIPT_ROOT "packages.config"
|
||||
|
||||
# Should we use mono?
|
||||
$UseMono = "";
|
||||
if($Mono.IsPresent) {
|
||||
Write-Verbose -Message "Using the Mono based scripting engine."
|
||||
$UseMono = "-mono"
|
||||
}
|
||||
|
||||
# Is this a dry run?
|
||||
$UseDryRun = "";
|
||||
if($WhatIf.IsPresent) {
|
||||
$UseDryRun = "-dryrun"
|
||||
}
|
||||
|
||||
# Make sure tools folder exists
|
||||
if ((Test-Path $PSScriptRoot) -and !(Test-Path $TOOLS_DIR)) {
|
||||
Write-Verbose -Message "Creating tools directory..."
|
||||
New-Item -Path $TOOLS_DIR -Type directory | out-null
|
||||
}
|
||||
|
||||
# Try download NuGet.exe if not exists
|
||||
if (!(Test-Path $NUGET_EXE)) {
|
||||
Write-Verbose -Message "Downloading NuGet.exe..."
|
||||
try {
|
||||
(New-Object System.Net.WebClient).DownloadFile($NUGET_URL, $NUGET_EXE)
|
||||
} catch {
|
||||
Throw "Could not download NuGet.exe."
|
||||
}
|
||||
}
|
||||
|
||||
# Save nuget.exe path to environment to be available to child processed
|
||||
$ENV:NUGET_EXE = $NUGET_EXE
|
||||
|
||||
# Restore tools from NuGet?
|
||||
if(-Not $SkipToolPackageRestore.IsPresent)
|
||||
{
|
||||
# Restore packages from NuGet.
|
||||
Push-Location
|
||||
Set-Location $TOOLS_DIR
|
||||
|
||||
Write-Verbose -Message "Restoring tools from NuGet..."
|
||||
$NuGetOutput = Invoke-Expression "&`"$NUGET_EXE`" install $PACKAGES_CONFIG -ExcludeVersion -OutputDirectory `"$TOOLS_DIR`""
|
||||
Write-Verbose -Message ($NuGetOutput | out-string)
|
||||
|
||||
Pop-Location
|
||||
if ($LASTEXITCODE -ne 0)
|
||||
{
|
||||
exit $LASTEXITCODE
|
||||
}
|
||||
}
|
||||
|
||||
# Make sure that Cake has been installed.
|
||||
if (!(Test-Path $CAKE_EXE)) {
|
||||
Throw "Could not find Cake.exe at $CAKE_EXE"
|
||||
}
|
||||
|
||||
# Start Cake
|
||||
Write-Host "Running build script..."
|
||||
Invoke-Expression "& `"$CAKE_EXE`" `"$Script`" -verbosity=`"$Verbosity`" $UseMono $UseDryRun $ScriptArgs"
|
||||
exit $LASTEXITCODE
|
||||
69
scripts/cake-bootstrap.sh
Normal file
69
scripts/cake-bootstrap.sh
Normal file
@@ -0,0 +1,69 @@
|
||||
#!/usr/bin/env bash
|
||||
###############################################################
|
||||
# This is the Cake bootstrapper script that is responsible for
|
||||
# downloading Cake and all specified tools from NuGet.
|
||||
###############################################################
|
||||
|
||||
# Define directories.
|
||||
SCRIPT_DIR=$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )
|
||||
TOOLS_DIR=$SCRIPT_DIR/../.tools
|
||||
export NUGET_EXE=$TOOLS_DIR/nuget.exe
|
||||
CAKE_EXE=$TOOLS_DIR/Cake/Cake.exe
|
||||
PACKAGES_CONFIG=$SCRIPT_DIR/packages.config
|
||||
|
||||
# Define default arguments.
|
||||
SCRIPT="build.cake"
|
||||
VERBOSITY="verbose"
|
||||
DRYRUN=
|
||||
SHOW_VERSION=false
|
||||
SCRIPT_ARGUMENTS=()
|
||||
|
||||
# Parse arguments.
|
||||
for i in "$@"; do
|
||||
case $1 in
|
||||
-s|--script) SCRIPT="$2"; shift ;;
|
||||
-v|--verbosity) VERBOSITY="$2"; shift ;;
|
||||
-d|--dryrun) DRYRUN="-dryrun" ;;
|
||||
--version) SHOW_VERSION=true ;;
|
||||
--) shift; SCRIPT_ARGUMENTS+=("$@"); break ;;
|
||||
*) SCRIPT_ARGUMENTS+=("$1") ;;
|
||||
esac
|
||||
shift
|
||||
done
|
||||
|
||||
# Make sure the tools folder exist.
|
||||
if [ ! -d "$TOOLS_DIR" ]; then
|
||||
mkdir "$TOOLS_DIR"
|
||||
fi
|
||||
|
||||
# Download NuGet if it does not exist.
|
||||
if [ ! -f "$NUGET_EXE" ]; then
|
||||
echo "Downloading NuGet..."
|
||||
curl -Lsfo "$NUGET_EXE" https://dist.nuget.org/win-x86-commandline/v3.3.0/nuget.exe
|
||||
if [ $? -ne 0 ]; then
|
||||
echo "An error occured while downloading nuget.exe."
|
||||
exit 1
|
||||
fi
|
||||
fi
|
||||
|
||||
# Restore tools from NuGet.
|
||||
pushd "$TOOLS_DIR" >/dev/null
|
||||
mono "$NUGET_EXE" install "$PACKAGES_CONFIG" -ExcludeVersion -OutputDirectory "$TOOLS_DIR"
|
||||
if [ $? -ne 0 ]; then
|
||||
echo "Could not restore NuGet packages."
|
||||
exit 1
|
||||
fi
|
||||
popd >/dev/null
|
||||
|
||||
# Make sure that Cake has been installed.
|
||||
if [ ! -f "$CAKE_EXE" ]; then
|
||||
echo "Could not find Cake.exe at '$CAKE_EXE'."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Start Cake
|
||||
if $SHOW_VERSION; then
|
||||
exec mono "$CAKE_EXE" -version
|
||||
else
|
||||
exec mono "$CAKE_EXE" $SCRIPT -verbosity=$VERBOSITY $DRYRUN "${SCRIPT_ARGUMENTS[@]}"
|
||||
fi
|
||||
5
scripts/packages.config
Normal file
5
scripts/packages.config
Normal file
@@ -0,0 +1,5 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<packages>
|
||||
<package id="Cake" version="0.10.1" />
|
||||
<package id="Newtonsoft.Json" version="8.0.3" />
|
||||
</packages>
|
||||
204
scripts/runhelpers.cake
Normal file
204
scripts/runhelpers.cake
Normal file
@@ -0,0 +1,204 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
|
||||
/// <summary>
|
||||
/// Class encompassing the optional settings for running processes.
|
||||
/// </summary>
|
||||
public class RunOptions
|
||||
{
|
||||
/// <summary>
|
||||
/// The working directory of the process.
|
||||
/// </summary>
|
||||
public string WorkingDirectory { get; set; }
|
||||
/// <summary>
|
||||
/// Container logging the StandardOutput content.
|
||||
/// </summary>
|
||||
public IList<string> StandardOutputListing { get; set; }
|
||||
/// <summary>
|
||||
/// Desired maximum time-out for the process
|
||||
/// </summary>
|
||||
public int TimeOut { get; set; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Wrapper for the exit code and state.
|
||||
/// Used to query the result of an execution with method calls.
|
||||
/// </summary>
|
||||
public struct ExitStatus
|
||||
{
|
||||
private int _code;
|
||||
private bool _timeOut;
|
||||
/// <summary>
|
||||
/// Default constructor when the execution finished.
|
||||
/// </summary>
|
||||
/// <param name="code">The exit code</param>
|
||||
public ExitStatus(int code)
|
||||
{
|
||||
this._code = code;
|
||||
this._timeOut = false;
|
||||
}
|
||||
/// <summary>
|
||||
/// Default constructor when the execution potentially timed out.
|
||||
/// </summary>
|
||||
/// <param name="code">The exit code</param>
|
||||
/// <param name="timeOut">True if the execution timed out</param>
|
||||
public ExitStatus(int code, bool timeOut)
|
||||
{
|
||||
this._code = code;
|
||||
this._timeOut = timeOut;
|
||||
}
|
||||
/// <summary>
|
||||
/// Flag signalling that the execution timed out.
|
||||
/// </summary>
|
||||
public bool DidTimeOut { get { return _timeOut; } }
|
||||
/// <summary>
|
||||
/// Implicit conversion from ExitStatus to the exit code.
|
||||
/// </summary>
|
||||
/// <param name="exitStatus">The exit status</param>
|
||||
/// <returns>The exit code</returns>
|
||||
public static implicit operator int(ExitStatus exitStatus)
|
||||
{
|
||||
return exitStatus._code;
|
||||
}
|
||||
/// <summary>
|
||||
/// Trigger Exception for non-zero exit code.
|
||||
/// </summary>
|
||||
/// <param name="errorMessage">The message to use in the Exception</param>
|
||||
/// <returns>The exit status for further queries</returns>
|
||||
public ExitStatus ExceptionOnError(string errorMessage)
|
||||
{
|
||||
if (this._code != 0)
|
||||
{
|
||||
throw new Exception(errorMessage);
|
||||
}
|
||||
return this;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Run the given executable with the given arguments.
|
||||
/// </summary>
|
||||
/// <param name="exec">Executable to run</param>
|
||||
/// <param name="args">Arguments</param>
|
||||
/// <returns>The exit status for further queries</returns>
|
||||
ExitStatus Run(string exec, string args)
|
||||
{
|
||||
return Run(exec, args, new RunOptions());
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Run the given executable with the given arguments.
|
||||
/// </summary>
|
||||
/// <param name="exec">Executable to run</param>
|
||||
/// <param name="args">Arguments</param>
|
||||
/// <param name="workingDirectory">Working directory</param>
|
||||
/// <returns>The exit status for further queries</returns>
|
||||
ExitStatus Run(string exec, string args, string workingDirectory)
|
||||
{
|
||||
return Run(exec, args,
|
||||
new RunOptions()
|
||||
{
|
||||
WorkingDirectory = workingDirectory
|
||||
});
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Run the given executable with the given arguments.
|
||||
/// </summary>
|
||||
/// <param name="exec">Executable to run</param>
|
||||
/// <param name="args">Arguments</param>
|
||||
/// <param name="runOptions">Optional settings</param>
|
||||
/// <returns>The exit status for further queries</returns>
|
||||
ExitStatus Run(string exec, string args, RunOptions runOptions)
|
||||
{
|
||||
var workingDirectory = runOptions.WorkingDirectory ?? System.IO.Directory.GetCurrentDirectory();
|
||||
var process = System.Diagnostics.Process.Start(
|
||||
new ProcessStartInfo(exec, args)
|
||||
{
|
||||
WorkingDirectory = workingDirectory,
|
||||
UseShellExecute = false,
|
||||
RedirectStandardOutput = runOptions.StandardOutputListing != null
|
||||
});
|
||||
if (runOptions.StandardOutputListing != null)
|
||||
{
|
||||
process.OutputDataReceived += (s, e) =>
|
||||
{
|
||||
if (e.Data != null)
|
||||
{
|
||||
runOptions.StandardOutputListing.Add(e.Data);
|
||||
}
|
||||
};
|
||||
process.BeginOutputReadLine();
|
||||
}
|
||||
if (runOptions.TimeOut == 0)
|
||||
{
|
||||
process.WaitForExit();
|
||||
return new ExitStatus(process.ExitCode);
|
||||
}
|
||||
else
|
||||
{
|
||||
bool finished = process.WaitForExit(runOptions.TimeOut);
|
||||
if (finished)
|
||||
{
|
||||
return new ExitStatus(process.ExitCode);
|
||||
}
|
||||
else
|
||||
{
|
||||
KillProcessTree(process);
|
||||
return new ExitStatus(0, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Run restore with the given arguments
|
||||
/// </summary>
|
||||
/// <param name="exec">Executable to run</param>
|
||||
/// <param name="args">Arguments</param>
|
||||
/// <param name="runOptions">Optional settings</param>
|
||||
/// <returns>The exit status for further queries</returns>
|
||||
ExitStatus RunRestore(string exec, string args, string workingDirectory)
|
||||
{
|
||||
Information("Restoring packages....");
|
||||
var p = StartAndReturnProcess(exec,
|
||||
new ProcessSettings
|
||||
{
|
||||
Arguments = args,
|
||||
RedirectStandardOutput = true,
|
||||
WorkingDirectory = workingDirectory
|
||||
});
|
||||
p.WaitForExit();
|
||||
var exitCode = p.GetExitCode();
|
||||
|
||||
if (exitCode == 0)
|
||||
{
|
||||
Information("Package restore successful!");
|
||||
}
|
||||
else
|
||||
{
|
||||
Error(string.Join("\n", p.GetStandardOutput()));
|
||||
}
|
||||
return new ExitStatus(exitCode);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Kill the given process and all its child processes.
|
||||
/// </summary>
|
||||
/// <param name="process">Root process</param>
|
||||
public void KillProcessTree(Process process)
|
||||
{
|
||||
// Child processes are not killed on Windows by default
|
||||
// Use TASKKILL to kill the process hierarchy rooted in the process
|
||||
if (IsRunningOnWindows())
|
||||
{
|
||||
StartProcess($"TASKKILL",
|
||||
new ProcessSettings
|
||||
{
|
||||
Arguments = $"/PID {process.Id} /T /F",
|
||||
});
|
||||
}
|
||||
else
|
||||
{
|
||||
process.Kill();
|
||||
}
|
||||
}
|
||||
@@ -13,18 +13,29 @@
|
||||
"Microsoft.SqlServer.Smo": "140.1.5",
|
||||
"System.Security.SecureString": "4.0.0",
|
||||
"System.Collections.Specialized": "4.0.1",
|
||||
"System.ComponentModel.TypeConverter": "4.1.0",
|
||||
"System.Diagnostics.TraceSource": "4.0.0"
|
||||
"System.ComponentModel.TypeConverter": "4.1.0",
|
||||
"System.Diagnostics.TraceSource": "4.0.0",
|
||||
"NETStandard.Library": "1.6.0",
|
||||
"Microsoft.NETCore.Runtime.CoreCLR": "1.0.2",
|
||||
"Microsoft.NETCore.DotNetHostPolicy": "1.0.1",
|
||||
"System.Diagnostics.Process": "4.1.0",
|
||||
"System.Threading.Thread": "4.0.0"
|
||||
},
|
||||
"frameworks": {
|
||||
"netcoreapp1.0": {
|
||||
"dependencies": {
|
||||
"Microsoft.NETCore.App": {
|
||||
"type": "platform",
|
||||
"version": "1.0.0"
|
||||
}
|
||||
},
|
||||
"imports": "dnxcore50"
|
||||
"imports": "dnxcore50"
|
||||
}
|
||||
},
|
||||
"runtimes": {
|
||||
"win7-x64": {},
|
||||
"win7-x86": {},
|
||||
"osx.10.11-x64": {},
|
||||
"ubuntu.14.04-x64": {},
|
||||
"ubuntu.16.04-x64": {},
|
||||
"centos.7-x64": {},
|
||||
"rhel.7.2-x64": {},
|
||||
"debian.8-x64": {},
|
||||
"fedora.23-x64": {},
|
||||
"opensuse.13.2-x64": {}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user