Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[WIP] csx build script spike #232

Closed
wants to merge 14 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ _NCrunch_NServiceBus/*
logs
run-git.cmd
src/Chocolatey/Build/*
.nuget/

installer/[F|f]iles
installer/[C|c]ustom[A|a]ctions
Expand Down
29 changes: 29 additions & 0 deletions build.cmd
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
:: the windows shell, so amazing

:: options
@echo Off
cd %~dp0
setlocal

:: determine cache dir
set NUGET_CACHE_DIR=%LocalAppData%\.nuget\v3.4.4

:: download nuget to cache dir
set NUGET_URL=https://dist.nuget.org/win-x86-commandline/v3.4.4/NuGet.exe
if not exist %NUGET_CACHE_DIR%\NuGet.exe (
if not exist %NUGET_CACHE_DIR% md %NUGET_CACHE_DIR%
echo Downloading '%NUGET_URL%'' to '%NUGET_CACHE_DIR%\NuGet.exe'...
@powershell -NoProfile -ExecutionPolicy unrestricted -Command "$ProgressPreference = 'SilentlyContinue'; Invoke-WebRequest '%NUGET_URL%' -OutFile '%NUGET_CACHE_DIR%\NuGet.exe'"
)

:: copy nuget locally
if not exist .nuget\NuGet.exe (
if not exist .nuget md .nuget
copy %NUGET_CACHE_DIR%\NuGet.exe .nuget\NuGet.exe > nul
)

:: restore packages
.nuget\NuGet.exe restore .\src\NServiceBus.RabbitMQ.sln -MSBuildVersion 14

:: run script
"%ProgramFiles(x86)%\MSBuild\14.0\Bin\csi.exe" build.csx %*
213 changes: 213 additions & 0 deletions build.csx
Original file line number Diff line number Diff line change
@@ -0,0 +1,213 @@
#r "System.IO.Compression.FileSystem.dll"

using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Globalization;
using System.IO;
using System.IO.Compression;
using System.Linq;
using System.Net;

// locations
var resharperCltUrl = "https://download.jetbrains.com/resharper/JetBrains.ReSharper.CommandLineTools.2016.2.20160912.114811.zip";
var resharperCltPath = $"{Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData)}/.resharper/JetBrains.ReSharper.CommandLineTools.2016.2.20160912.114811.zip";
var inspectCodePath = "./.resharper/inspectcode.exe";
var msBuild = $"{Environment.GetFolderPath(Environment.SpecialFolder.ProgramFilesX86)}/MSBuild/14.0/Bin/msbuild.exe";
var solution = "./src/NServiceBus.RabbitMq.sln";
var dotSettings = "./src/NServiceBus.RabbitMQ.sln.DotSettings";
var nunit = "./src/packages/NUnit.ConsoleRunner.3.4.1/tools/nunit3-console.exe";
var unitTests = "./src/NServiceBus.RabbitMQ.Tests/bin/Release/NServiceBus.Transports.RabbitMQ.Tests.dll";
var acceptanceTests = "./src/NServiceBus.RabbitMQ.AcceptanceTests/bin/Release/NServiceBus.RabbitMQ.AcceptanceTests.dll";
var transportTests = "./src/NServiceBus.Transport.RabbitMQ.TransportTests/bin/Release/NServiceBus.Transport.RabbitMQ.TransportTests.dll";

// targets
var targets = new Dictionary<string, Target>();

targets.Add("default", new Target { DependOn = new[] { "build", "inspect", "unit-test", "acceptance-test", "transport-test" } });

targets.Add("build", new Target { Do = () => Cmd(msBuild, $"{solution} /p:Configuration=Release /nologo /m /v:m /nr:false"), });

targets.Add(
"download-resharper-clt",
new Target { Outputs = new[] { resharperCltPath }, Do = () => Download(resharperCltUrl, resharperCltPath), });

targets.Add(
"unzip-resharper-clt",
new Target
{
Inputs = new[] { resharperCltPath },
Outputs = new[] { inspectCodePath },
Do = () => ZipFile.ExtractToDirectory(resharperCltPath, Path.GetDirectoryName(inspectCodePath)),
});

targets.Add(
"inspect",
new Target
{
DependOn = new[] { "build" },
Inputs = new[] { inspectCodePath },
Do = () => Cmd(inspectCodePath, $"--profile={dotSettings} {solution}"),
});

targets.Add("unit-test", new Target { DependOn = new[] { "build" }, Do = () => Cmd(nunit, unitTests), });

targets.Add("acceptance-test", new Target { DependOn = new[] { "build" }, Do = () => Cmd(nunit, acceptanceTests), });

targets.Add("transport-test", new Target { DependOn = new[] { "build" }, Do = () => Cmd(nunit, transportTests), });

// target running boiler plate
Run(Args, targets);

public class Target
{
public string[] DependOn { get; set; }

public string[] Inputs { get; set; }

public string[] Outputs { get; set; }

public Action Do { get; set; }
}

public static void Run(IList<string> args, IDictionary<string, Target> targets)
{
var argsOptions = args.Where(arg => arg.StartsWith("-", StringComparison.Ordinal)).ToList();
var argsTargets = args.Except(argsOptions).ToList();

foreach (var option in argsOptions)
{
switch (option)
{
case "-H":
case "-h":
case "-?":
Console.WriteLine("Usage: <script-runner> build.csx [<options>] [<targets>]");
Console.WriteLine();
Console.WriteLine("script-runner: A C# script runner. E.g. csi.exe.");
Console.WriteLine();
Console.WriteLine("options:");
Console.WriteLine(" -T Display the targets, then exit");
Console.WriteLine();
Console.WriteLine("targets: A list of targets to run. If not specified, 'default' target will be run.");
Console.WriteLine();
Console.WriteLine("Examples:");
Console.WriteLine(" csi.exe build.csx");
Console.WriteLine(" csi.exe build.csx -T");
Console.WriteLine(" csi.exe build.csx test package");
return;
case "-T":
foreach (var target in targets)
{
Console.WriteLine(target.Key);
}

return;
default:
Console.WriteLine($"Unknown option '{option}'.");
return;
}
}

var targetNames = argsTargets.Any() ? argsTargets : new List<string> { "default" };
var targetsRan = new HashSet<string>();

targetNames.ForEach(name => RunTarget(name, targets, targetsRan));

Console.WriteLine($"Target(s) {string.Join(", ", targetNames.Select(name => $"'{name}'"))} succeeded.");
}

public static void RunTarget(string name, IDictionary<string, Target> targets, ISet<string> targetsRan)
{
Target target;
if (!targets.TryGetValue(name, out target))
{
throw new InvalidOperationException($"Target '{name}' not found.");
}

targetsRan.Add(name);

var outputs = target.Outputs ?? Enumerable.Empty<string>();
if (outputs.Any() && !outputs.Any(output => !File.Exists(output)))
{
Console.WriteLine($"Skipping target '{name}' since all outputs are present.");
return;
}

var inputs = target.Inputs ?? Enumerable.Empty<string>();
var dependencies = (target.DependOn ?? Enumerable.Empty<string>()).Concat(
targets.Where(t => (t.Value.Outputs ?? Enumerable.Empty<string>()).Intersect(inputs).Any()).Select(t => t.Key));

if (dependencies.Any())
{
Console.WriteLine($"Running dependencies for target '{name}'...");
foreach (var dependencyName in dependencies.Except(targetsRan))
{
RunTarget(dependencyName, targets, targetsRan);
}
}

if (target.Do != null)
{
Console.WriteLine($"Running target '{name}'...");
target.Do.Invoke();
}
}

// target writing boiler plate
public static void Cmd(string fileName, string args)
{
var info = new ProcessStartInfo
{
FileName = "\"" + fileName + "\"",
Arguments = args,
UseShellExecute = false,
};

Console.WriteLine($"Running '{info.FileName} {info.Arguments}'...");

using (var process = new Process())
{
process.StartInfo = info;
process.Start();
process.WaitForExit();
if (process.ExitCode != 0)
{
var message = string.Format(
CultureInfo.InvariantCulture,
"The command exited with code {0}.",
process.ExitCode.ToString(CultureInfo.InvariantCulture));

throw new InvalidOperationException(message);
}
}
}

public static void Download(string url, string path)
{
var directory = Path.GetDirectoryName(path);
if (!Directory.Exists(directory))
{
Directory.CreateDirectory(directory);
}

var lastUpdate = DateTime.Now;
var lastPercentage = 0;
using (var client = new WebClient())
{
client.DownloadProgressChanged += (sender, e) =>
{
var now = DateTime.Now;
if (now - lastUpdate >= TimeSpan.FromSeconds(1) && e.ProgressPercentage >= lastPercentage + 10)
{
lastUpdate = now;
lastPercentage = (int)Math.Round(e.ProgressPercentage / 10d, 0) * 10;
Console.WriteLine($"\rDownloading '{url}' ({lastPercentage}%)...");
}
};

client.DownloadFileCompleted += (sender, e) => Console.WriteLine($"\rDownloaded '{url}'.");

client.DownloadFileTaskAsync(url, path).GetAwaiter().GetResult();
}
}
1 change: 1 addition & 0 deletions src/.nuget/packages.config
Original file line number Diff line number Diff line change
Expand Up @@ -3,4 +3,5 @@
<package id="ConsoleTweet" version="0.1.0" />
<package id="GitHubReleaseNotes" version="0.1.1" />
<package id="NuGet.CommandLine" version="2.8.3" />
<package id="NUnit.ConsoleRunner" version="3.4.1" />
</packages>
2 changes: 2 additions & 0 deletions src/NServiceBus.RabbitMQ.sln
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = ".nuget", ".nuget", "{FF6C08
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{87D8530F-671C-4E77-8B93-BCE848FCF2F4}"
ProjectSection(SolutionItems) = preProject
..\build.cmd = ..\build.cmd
..\build.csx = ..\build.csx
..\packaging\nuget\NServiceBus.RabbitMQ.nuspec = ..\packaging\nuget\NServiceBus.RabbitMQ.nuspec
EndProjectSection
EndProject
Expand Down