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:
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();
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user