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();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -14,17 +14,28 @@
|
|||||||
"System.Security.SecureString": "4.0.0",
|
"System.Security.SecureString": "4.0.0",
|
||||||
"System.Collections.Specialized": "4.0.1",
|
"System.Collections.Specialized": "4.0.1",
|
||||||
"System.ComponentModel.TypeConverter": "4.1.0",
|
"System.ComponentModel.TypeConverter": "4.1.0",
|
||||||
"System.Diagnostics.TraceSource": "4.0.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": {
|
"frameworks": {
|
||||||
"netcoreapp1.0": {
|
"netcoreapp1.0": {
|
||||||
"dependencies": {
|
"imports": "dnxcore50"
|
||||||
"Microsoft.NETCore.App": {
|
|
||||||
"type": "platform",
|
|
||||||
"version": "1.0.0"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"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