├── lib ├── Cake.Core.dll ├── Cake.Common.dll ├── Cake.NuGet.dll ├── Nuget.Core.dll └── Cake.Testing.dll ├── src ├── CakeBoss.Agent │ ├── Icon.ico │ ├── Interfaces │ │ ├── ITerminationService.cs │ │ └── IAgentService.cs │ ├── Properties │ │ └── AssemblyInfo.cs │ ├── Registry │ │ └── AgentRoot.cs │ ├── Utils │ │ └── UptimeUtils.cs │ ├── Aliases │ │ ├── AgentSettings.cs │ │ ├── TerminationAliases.cs │ │ ├── ApiAliases.cs │ │ └── AgentAliases.cs │ ├── Nancy │ │ ├── ServiceModule.cs │ │ ├── ServiceStartup.cs │ │ └── ServiceBootstrapper.cs │ ├── App.config │ ├── packages.config │ ├── Service │ │ ├── TerminationService.cs │ │ └── AgentService.cs │ └── Program.cs ├── Cake.Host │ ├── Diagnostics │ │ ├── Formatting │ │ │ ├── FormatToken.cs │ │ │ ├── LiteralToken.cs │ │ │ ├── PropertyToken.cs │ │ │ └── FormatParser.cs │ │ ├── IVerbosityAware.cs │ │ ├── ConsolePalette.cs │ │ └── CakeBuildLog.cs │ ├── Scripting │ │ ├── Mono │ │ │ ├── MonoScriptHostProxy.cs │ │ │ ├── CodeGen │ │ │ │ ├── Parsing │ │ │ │ │ ├── ScriptTokenType.cs │ │ │ │ │ ├── ScriptBlock.cs │ │ │ │ │ ├── ScriptToken.cs │ │ │ │ │ ├── ScriptBuffer.cs │ │ │ │ │ └── ScriptTokenizer.cs │ │ │ │ ├── MonoScriptProcessor.cs │ │ │ │ └── MonoCodeGenerator.cs │ │ │ ├── MonoScriptEngine.cs │ │ │ ├── MonoConsoleReportPrinter.cs │ │ │ └── MonoScriptSession.cs │ │ ├── Roslyn │ │ │ ├── RoslynCodeGenerator.cs │ │ │ ├── RoslynScriptEngine.cs │ │ │ ├── Stable │ │ │ │ ├── RoslynScriptSession.cs │ │ │ │ └── RoslynScriptSessionFactory.cs │ │ │ └── Nightly │ │ │ │ ├── RoslynNightlyScriptSession.cs │ │ │ │ └── RoslynNightlyScriptSessionFactory.cs │ │ ├── BuildScriptHost.cs │ │ ├── DryRunExecutionStrategy.cs │ │ ├── DryRunScriptHost.cs │ │ └── DescriptionScriptHost.cs │ ├── Commands │ │ ├── ICommand.cs │ │ ├── ErrorCommandDecorator.cs │ │ ├── DryRunCommand.cs │ │ ├── BuildCommand.cs │ │ ├── DescriptionCommand.cs │ │ ├── ICommandFactory.cs │ │ ├── CommandFactory.cs │ │ ├── HelpCommand.cs │ │ └── VersionCommand.cs │ ├── Arguments │ │ ├── IArgumentParser.cs │ │ ├── VerbosityParser.cs │ │ └── ArgumentTokenizer.cs │ ├── app.config │ ├── Properties │ │ └── AssemblyInfo.cs │ ├── packages.config │ ├── CakeConsole.cs │ ├── CakeArguments.cs │ ├── CakeReportPrinter.cs │ ├── CakeOptions.cs │ ├── NuGet │ │ └── NuGetVersionUtilityAdapter.cs │ └── CakeApplication.cs ├── Cake.CakeBoss │ ├── packages.config │ ├── Properties │ │ ├── Namespaces.cs │ │ └── AssemblyInfo.cs │ ├── Settings │ │ └── RemoteSettings.cs │ ├── Cake.CakeBoss.csproj │ └── Aliases │ │ └── AgentAliases.cs ├── CakeBoss.Host │ ├── Interfaces │ │ └── IAuthenticationService.cs │ ├── Commands │ │ ├── LogCommand.cs │ │ ├── UpdateCommand.cs │ │ └── RunCommand.cs │ ├── Extensions │ │ ├── HashSetExtensions.cs │ │ ├── CakeContextExtensions.cs │ │ └── HostSettingsExtensions.cs │ ├── Properties │ │ └── AssemblyInfo.cs │ ├── Auth │ │ ├── User.cs │ │ ├── AuthenticationService.cs │ │ └── HostSettings.cs │ ├── Nancy │ │ ├── UserIdentity.cs │ │ └── UserValidator.cs │ ├── app.config │ ├── Tasks │ │ └── TaskRegistry.cs │ ├── Console │ │ ├── ConsoleOutput.cs │ │ ├── HostLog.cs │ │ └── HostConsole.cs │ ├── Aliases │ │ ├── HostAliases.cs │ │ └── ScheduleAliases.cs │ ├── packages.config │ ├── Host │ │ ├── ScriptConventions.cs │ │ └── HostApplication.cs │ └── Registry │ │ └── HostRoot.cs ├── SolutionInfo.cs ├── CakeBoss.Agent.Tests │ ├── Tests │ │ └── AgentTests.cs │ ├── app.config │ ├── Properties │ │ └── AssemblyInfo.cs │ ├── Config │ │ ├── Startup.cs │ │ └── UnitTestBootstrapper.cs │ └── packages.config └── CakeBoss.sln ├── script ├── Install.bat ├── Deploy.bat ├── Uninstall.bat ├── Release.cake └── Test.cake ├── appveyor.yml ├── .gitattributes ├── .gitignore ├── LICENSE ├── nuspec └── Cake.CakeBoss.nuspec └── ReleaseNotes.md /lib/Cake.Core.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SharpeRAD/CakeBoss/HEAD/lib/Cake.Core.dll -------------------------------------------------------------------------------- /lib/Cake.Common.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SharpeRAD/CakeBoss/HEAD/lib/Cake.Common.dll -------------------------------------------------------------------------------- /lib/Cake.NuGet.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SharpeRAD/CakeBoss/HEAD/lib/Cake.NuGet.dll -------------------------------------------------------------------------------- /lib/Nuget.Core.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SharpeRAD/CakeBoss/HEAD/lib/Nuget.Core.dll -------------------------------------------------------------------------------- /lib/Cake.Testing.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SharpeRAD/CakeBoss/HEAD/lib/Cake.Testing.dll -------------------------------------------------------------------------------- /src/CakeBoss.Agent/Icon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SharpeRAD/CakeBoss/HEAD/src/CakeBoss.Agent/Icon.ico -------------------------------------------------------------------------------- /src/Cake.Host/Diagnostics/Formatting/FormatToken.cs: -------------------------------------------------------------------------------- 1 | namespace Cake.Host.Diagnostics.Formatting 2 | { 3 | public abstract class FormatToken 4 | { 5 | public abstract string Render(object[] args); 6 | } 7 | } -------------------------------------------------------------------------------- /src/Cake.CakeBoss/packages.config: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /script/Install.bat: -------------------------------------------------------------------------------- 1 | @ECHO OFF 2 | 3 | @setlocal enableextensions 4 | @cd /d "%~dp0" 5 | 6 | if exist "%cd%\CakeBoss.Agent.exe" ( 7 | SET file=%cd%\CakeBoss.Agent.exe 8 | ) else ( 9 | SET file=%cd%\CakeBoss.Server.exe 10 | ) 11 | ECHO %file% 12 | 13 | CALL "%file%" install 14 | PAUSE -------------------------------------------------------------------------------- /script/Deploy.bat: -------------------------------------------------------------------------------- 1 | @ECHO OFF 2 | 3 | @setlocal enableextensions 4 | @cd /d "%~dp0" 5 | 6 | if exist "%cd%\CakeBoss.Agent.exe" ( 7 | SET file=%cd%\CakeBoss.Agent.exe 8 | ) else ( 9 | SET file=%cd%\CakeBoss.Server.exe 10 | ) 11 | ECHO %file% 12 | 13 | CALL "%file%" -target=Deploy 14 | PAUSE -------------------------------------------------------------------------------- /script/Uninstall.bat: -------------------------------------------------------------------------------- 1 | @ECHO OFF 2 | 3 | @setlocal enableextensions 4 | @cd /d "%~dp0" 5 | 6 | if exist "%cd%\CakeBoss.Agent.exe" ( 7 | SET file=%cd%\CakeBoss.Agent.exe 8 | ) else ( 9 | SET file=%cd%\CakeBoss.Server.exe 10 | ) 11 | ECHO %file% 12 | 13 | CALL "%file%" uninstall 14 | PAUSE -------------------------------------------------------------------------------- /src/CakeBoss.Host/Interfaces/IAuthenticationService.cs: -------------------------------------------------------------------------------- 1 | #region Using Statements 2 | using System; 3 | #endregion 4 | 5 | 6 | 7 | namespace CakeBoss.Host 8 | { 9 | public interface IAuthenticationService 10 | { 11 | bool ValidUser(string username, string password); 12 | 13 | bool ValidApiKey(string apiKey); 14 | } 15 | } -------------------------------------------------------------------------------- /src/Cake.CakeBoss/Properties/Namespaces.cs: -------------------------------------------------------------------------------- 1 | using System.Runtime.CompilerServices; 2 | // ReSharper disable CheckNamespace 3 | 4 | 5 | namespace Cake.CakeBoss 6 | { 7 | /// 8 | /// This namespace contains CakeBoss aliases and related members. 9 | /// 10 | [CompilerGenerated] 11 | internal class NamespaceDoc 12 | { 13 | } 14 | } -------------------------------------------------------------------------------- /appveyor.yml: -------------------------------------------------------------------------------- 1 | # Build script 2 | init: 3 | - git config --global core.autocrlf true 4 | 5 | # Build script 6 | build_script: 7 | - cmd: powershell -NoProfile -ExecutionPolicy unrestricted -Command .\build.ps1 -Target "AppVeyor" 8 | 9 | # Tests 10 | test: off 11 | 12 | # Branches to build 13 | branches: 14 | # Whitelist 15 | only: 16 | - develop 17 | - main 18 | -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | # Auto detect text files and perform LF normalization 2 | * text=auto 3 | 4 | # Custom for Visual Studio 5 | *.cs diff=csharp 6 | 7 | # Standard to msysgit 8 | *.doc diff=astextplain 9 | *.DOC diff=astextplain 10 | *.docx diff=astextplain 11 | *.DOCX diff=astextplain 12 | *.dot diff=astextplain 13 | *.DOT diff=astextplain 14 | *.pdf diff=astextplain 15 | *.PDF diff=astextplain 16 | *.rtf diff=astextplain 17 | *.RTF diff=astextplain 18 | -------------------------------------------------------------------------------- /src/Cake.Host/Scripting/Mono/MonoScriptHostProxy.cs: -------------------------------------------------------------------------------- 1 | using Cake.Core.Scripting; 2 | 3 | namespace Cake.Host.Scripting.Mono 4 | { 5 | /// 6 | /// Mono script host proxy. 7 | /// 8 | public class MonoScriptHostProxy 9 | { 10 | /// 11 | /// Gets or sets the script host. 12 | /// 13 | /// The script host. 14 | public static IScriptHost ScriptHost { get; set; } 15 | } 16 | } -------------------------------------------------------------------------------- /src/Cake.Host/Scripting/Mono/CodeGen/Parsing/ScriptTokenType.cs: -------------------------------------------------------------------------------- 1 | namespace Cake.Host.Scripting.Mono.CodeGen.Parsing 2 | { 3 | public enum ScriptTokenType 4 | { 5 | Word = 0, 6 | If = 1, 7 | Else = 2, 8 | While = 3, 9 | Switch = 4, 10 | String = 5, 11 | Semicolon = 6, 12 | LeftBrace = 7, 13 | RightBrace = 8, 14 | LeftParenthesis = 9, 15 | RightParenthesis = 10, 16 | Character = 11 17 | } 18 | } -------------------------------------------------------------------------------- /src/Cake.Host/Diagnostics/IVerbosityAware.cs: -------------------------------------------------------------------------------- 1 | using Cake.Core.Diagnostics; 2 | 3 | namespace Cake.Host.Diagnostics 4 | { 5 | /// 6 | /// Represents a verbosity aware log. 7 | /// 8 | public interface IVerbosityAwareLog : ICakeLog 9 | { 10 | /// 11 | /// Sets the verbosity. 12 | /// 13 | /// The desired verbosity. 14 | void SetVerbosity(Verbosity verbosity); 15 | } 16 | } -------------------------------------------------------------------------------- /src/CakeBoss.Agent/Interfaces/ITerminationService.cs: -------------------------------------------------------------------------------- 1 | #region Using Statements 2 | using System; 3 | #endregion 4 | 5 | 6 | 7 | namespace CakeBoss.Agent 8 | { 9 | public interface ITerminationService 10 | { 11 | #region Properties (2) 12 | bool Enabled { get; set; } 13 | 14 | int Interval { get; set; } 15 | #endregion 16 | 17 | 18 | 19 | 20 | 21 | #region Functions (1) 22 | bool Termination(); 23 | #endregion 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /src/Cake.Host/Commands/ICommand.cs: -------------------------------------------------------------------------------- 1 | namespace Cake.Host.Commands 2 | { 3 | /// 4 | /// Represents an executable command. 5 | /// 6 | public interface ICommand 7 | { 8 | /// 9 | /// Executes the command with the specified options. 10 | /// 11 | /// The options. 12 | /// true if the command exited successfully; otherwise, false. 13 | bool Execute(CakeOptions options); 14 | } 15 | } -------------------------------------------------------------------------------- /src/CakeBoss.Host/Commands/LogCommand.cs: -------------------------------------------------------------------------------- 1 | #region Using Statements 2 | using System; 3 | #endregion 4 | 5 | 6 | 7 | namespace CakeBoss.Host 8 | { 9 | public class LogCommand 10 | { 11 | #region Constructor (1) 12 | public LogCommand() 13 | { 14 | 15 | } 16 | #endregion 17 | 18 | 19 | 20 | 21 | 22 | #region Properties (2) 23 | public string Client { get; set; } 24 | 25 | public ConsoleOutput Output { get; set; } 26 | #endregion 27 | } 28 | } -------------------------------------------------------------------------------- /src/Cake.Host/Diagnostics/Formatting/LiteralToken.cs: -------------------------------------------------------------------------------- 1 | namespace Cake.Host.Diagnostics.Formatting 2 | { 3 | public sealed class LiteralToken : FormatToken 4 | { 5 | private readonly string _text; 6 | 7 | public string Text 8 | { 9 | get { return _text; } 10 | } 11 | 12 | public LiteralToken(string text) 13 | { 14 | _text = text; 15 | } 16 | 17 | public override string Render(object[] args) 18 | { 19 | return _text; 20 | } 21 | } 22 | } -------------------------------------------------------------------------------- /src/SolutionInfo.cs: -------------------------------------------------------------------------------- 1 | //------------------------------------------------------------------------------ 2 | // 3 | // This code was generated by Cake. 4 | // 5 | //------------------------------------------------------------------------------ 6 | using System.Reflection; 7 | 8 | [assembly: AssemblyProduct("CakeBoss")] 9 | [assembly: AssemblyVersion("0.1.5")] 10 | [assembly: AssemblyFileVersion("0.1.5")] 11 | [assembly: AssemblyInformationalVersion("0.1.5")] 12 | [assembly: AssemblyCopyright("Copyright (c) 2015 - 2016 Phillip Sharpe")] 13 | 14 | -------------------------------------------------------------------------------- /src/Cake.Host/Arguments/IArgumentParser.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | 3 | namespace Cake.Host.Arguments 4 | { 5 | /// 6 | /// Represents an argument parser. 7 | /// 8 | public interface IArgumentParser 9 | { 10 | /// 11 | /// Parses the specified arguments. 12 | /// 13 | /// The arguments to parse. 14 | /// A instance representing the arguments. 15 | CakeOptions Parse(IEnumerable args); 16 | } 17 | } -------------------------------------------------------------------------------- /src/CakeBoss.Host/Extensions/HashSetExtensions.cs: -------------------------------------------------------------------------------- 1 | #region Using Statements 2 | using System; 3 | using System.Collections.Generic; 4 | #endregion 5 | 6 | 7 | 8 | namespace CakeBoss.Host 9 | { 10 | public static class HashSetExtensions 11 | { 12 | public static void AddRange(this HashSet set, IEnumerable items) 13 | { 14 | if (items != null) 15 | { 16 | foreach (var item in items) 17 | { 18 | set.Add(item); 19 | } 20 | } 21 | } 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /src/CakeBoss.Host/Commands/UpdateCommand.cs: -------------------------------------------------------------------------------- 1 | #region Using Statements 2 | using System; 3 | #endregion 4 | 5 | 6 | 7 | namespace CakeBoss.Host 8 | { 9 | public class UpdateCommand 10 | { 11 | #region Constructor (1) 12 | public UpdateCommand() 13 | { 14 | 15 | } 16 | #endregion 17 | 18 | 19 | 20 | 21 | 22 | #region Properties (3) 23 | public string Group { get; set; } 24 | 25 | 26 | 27 | public string Name { get; set; } 28 | 29 | public string Contents { get; set; } 30 | #endregion 31 | } 32 | } -------------------------------------------------------------------------------- /src/CakeBoss.Host/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.CompilerServices; 3 | using System.Runtime.InteropServices; 4 | 5 | // General Information about an assembly is controlled through the following 6 | // set of attributes. Change these attribute values to modify the information 7 | // associated with an assembly. 8 | [assembly: AssemblyTitle("CakeBoss.Agent")] 9 | [assembly: AssemblyDescription("A host for the Cake-Build")] 10 | 11 | // The following GUID is for the ID of the typelib if this project is exposed to COM 12 | [assembly: Guid("206f12ed-5ffa-4333-a5a9-31c142648ac1")] 13 | -------------------------------------------------------------------------------- /src/Cake.Host/Commands/ErrorCommandDecorator.cs: -------------------------------------------------------------------------------- 1 | namespace Cake.Host.Commands 2 | { 3 | /// 4 | /// A command that decorates another command but always return failure. 5 | /// 6 | public sealed class ErrorCommandDecorator : ICommand 7 | { 8 | private readonly ICommand _command; 9 | 10 | public ErrorCommandDecorator(ICommand command) 11 | { 12 | _command = command; 13 | } 14 | 15 | public bool Execute(CakeOptions options) 16 | { 17 | _command.Execute(options); 18 | return false; 19 | } 20 | } 21 | } -------------------------------------------------------------------------------- /src/CakeBoss.Agent/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.CompilerServices; 3 | using System.Runtime.InteropServices; 4 | 5 | // General Information about an assembly is controlled through the following 6 | // set of attributes. Change these attribute values to modify the information 7 | // associated with an assembly. 8 | [assembly: AssemblyTitle("CakeBoss.Agent")] 9 | [assembly: AssemblyDescription("A windows service to run Cake-Build scripts")] 10 | 11 | // The following GUID is for the ID of the typelib if this project is exposed to COM 12 | [assembly: Guid("14449d2a-6115-476b-8f8a-78a1bf726299")] 13 | -------------------------------------------------------------------------------- /src/CakeBoss.Host/Auth/User.cs: -------------------------------------------------------------------------------- 1 | #region Using Statements 2 | using System; 3 | #endregion 4 | 5 | 6 | 7 | namespace CakeBoss.Host 8 | { 9 | public class User 10 | { 11 | #region Constructor (1) 12 | public User(string username, string password) 13 | { 14 | this.Username = username; 15 | this.Password = password; 16 | } 17 | #endregion 18 | 19 | 20 | 21 | 22 | 23 | #region Properties (2) 24 | public string Username { get; set; } 25 | 26 | public string Password { get; set; } 27 | #endregion 28 | } 29 | } -------------------------------------------------------------------------------- /src/CakeBoss.Host/Commands/RunCommand.cs: -------------------------------------------------------------------------------- 1 | #region Using Statements 2 | using System; 3 | using System.Collections.Generic; 4 | #endregion 5 | 6 | 7 | 8 | namespace CakeBoss.Host 9 | { 10 | public class RunCommand 11 | { 12 | #region Constructor (1) 13 | public RunCommand() 14 | { 15 | 16 | } 17 | #endregion 18 | 19 | 20 | 21 | 22 | 23 | #region Properties (3) 24 | public string Group { get; set; } 25 | 26 | 27 | 28 | public string Name { get; set; } 29 | 30 | public IDictionary Arguments { get; set; } 31 | #endregion 32 | } 33 | } -------------------------------------------------------------------------------- /src/CakeBoss.Agent/Registry/AgentRoot.cs: -------------------------------------------------------------------------------- 1 | #region Using Statements 2 | using LightInject; 3 | using Nancy; 4 | #endregion 5 | 6 | 7 | 8 | namespace CakeBoss.Agent 9 | { 10 | public class AgentRoot : ICompositionRoot 11 | { 12 | public void Compose(IServiceRegistry container) 13 | { 14 | //Register Agent 15 | container.Register(new PerContainerLifetime()); 16 | container.Register(new PerContainerLifetime()); 17 | 18 | 19 | 20 | //Register Nancy 21 | container.Register("Agent"); 22 | } 23 | } 24 | } -------------------------------------------------------------------------------- /src/CakeBoss.Agent.Tests/Tests/AgentTests.cs: -------------------------------------------------------------------------------- 1 | #region Using Statements 2 | using CakeBoss.Agent; 3 | 4 | using Xunit; 5 | #endregion 6 | 7 | 8 | 9 | namespace CakeBoss.Agent.Tests 10 | { 11 | public class ServiceTests 12 | { 13 | public static IAgentService _Service = null; 14 | 15 | 16 | 17 | public ServiceTests() 18 | { 19 | Startup.CreateContainer(); 20 | 21 | _Service = Startup.Container.GetInstance(); 22 | } 23 | 24 | 25 | 26 | /* 27 | [Fact] 28 | public void Service_Start() 29 | { 30 | Assert.True(_Service.RunTarget("Start", true)); 31 | } 32 | */ 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /src/CakeBoss.Agent.Tests/app.config: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /src/CakeBoss.Agent/Interfaces/IAgentService.cs: -------------------------------------------------------------------------------- 1 | #region Using Statements 2 | using System; 3 | using System.Collections.Generic; 4 | #endregion 5 | 6 | 7 | 8 | namespace CakeBoss.Agent 9 | { 10 | public interface IAgentService 11 | { 12 | #region Properties (1) 13 | string CurrentTask { get; set; } 14 | #endregion 15 | 16 | 17 | 18 | 19 | 20 | #region Functions (5) 21 | //Events 22 | void Start(IDictionary arguments); 23 | 24 | void Stop(); 25 | 26 | void Shutdown(); 27 | 28 | void Terminate(); 29 | 30 | 31 | 32 | //Run 33 | bool RunTarget(string target, bool load); 34 | #endregion 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /src/Cake.CakeBoss/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.CompilerServices; 3 | using System.Runtime.InteropServices; 4 | 5 | // General Information about an assembly is controlled through the following 6 | // set of attributes. Change these attribute values to modify the information 7 | // associated with an assembly. 8 | [assembly: AssemblyTitle("Cake.CakeBoss")] 9 | [assembly: AssemblyDescription("Cake-Build addin that extends allows you to control remote CakeBoss agents")] 10 | 11 | // Setting ComVisible to false makes the types in this assembly not visible 12 | // to COM components. If you need to access a type in this assembly from 13 | // COM, set the ComVisible attribute to true on that type. 14 | [assembly: ComVisible(false)] -------------------------------------------------------------------------------- /src/Cake.Host/app.config: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | -------------------------------------------------------------------------------- /src/CakeBoss.Host/Nancy/UserIdentity.cs: -------------------------------------------------------------------------------- 1 | #region Using Statements 2 | using System; 3 | using System.Collections.Generic; 4 | 5 | using Nancy.Security; 6 | #endregion 7 | 8 | 9 | 10 | namespace CakeBoss.Host 11 | { 12 | public class UserIdentity : IUserIdentity 13 | { 14 | #region Constructor (2) 15 | public UserIdentity() 16 | { 17 | 18 | } 19 | 20 | public UserIdentity(string username) 21 | { 22 | this.UserName = username; 23 | } 24 | #endregion 25 | 26 | 27 | 28 | 29 | 30 | #region Properties (2) 31 | public string UserName { get; set; } 32 | 33 | public IEnumerable Claims { get; set; } 34 | #endregion 35 | } 36 | } -------------------------------------------------------------------------------- /src/CakeBoss.Host/app.config: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | -------------------------------------------------------------------------------- /src/CakeBoss.Agent/Utils/UptimeUtils.cs: -------------------------------------------------------------------------------- 1 | #region Using Statements 2 | using System; 3 | using System.Diagnostics; 4 | #endregion 5 | 6 | 7 | 8 | namespace CakeBoss.Agent 9 | { 10 | public static class UptimeUtils 11 | { 12 | #region Functions (2) 13 | public static TimeSpan GetUptime() 14 | { 15 | using (var uptime = new PerformanceCounter("System", "System Up Time")) 16 | { 17 | uptime.NextValue(); 18 | 19 | return TimeSpan.FromSeconds(uptime.NextValue()); 20 | } 21 | } 22 | 23 | public static bool IsStartup() 24 | { 25 | return GetUptime() < new TimeSpan(0, 5, 0); 26 | } 27 | #endregion 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /src/Cake.Host/Diagnostics/ConsolePalette.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace Cake.Host.Diagnostics 4 | { 5 | public sealed class ConsolePalette 6 | { 7 | public ConsoleColor Background { get; set; } 8 | 9 | public ConsoleColor Foreground { get; set; } 10 | 11 | public ConsoleColor ArgumentBackground { get; set; } 12 | 13 | public ConsoleColor ArgumentForeground { get; set; } 14 | 15 | public ConsolePalette(ConsoleColor background, ConsoleColor foreground, 16 | ConsoleColor argumentBackground, ConsoleColor argumentForeground) 17 | { 18 | Background = background; 19 | Foreground = foreground; 20 | ArgumentBackground = argumentBackground; 21 | ArgumentForeground = argumentForeground; 22 | } 23 | } 24 | } -------------------------------------------------------------------------------- /src/Cake.Host/Scripting/Mono/CodeGen/Parsing/ScriptBlock.cs: -------------------------------------------------------------------------------- 1 | namespace Cake.Host.Scripting.Mono.CodeGen.Parsing 2 | { 3 | public sealed class ScriptBlock 4 | { 5 | private readonly int _index; 6 | private readonly string _content; 7 | private readonly bool _hasScope; 8 | 9 | public int Index 10 | { 11 | get { return _index; } 12 | } 13 | 14 | public string Content 15 | { 16 | get { return _content; } 17 | } 18 | 19 | public bool HasScope 20 | { 21 | get { return _hasScope; } 22 | } 23 | 24 | public ScriptBlock(int index, string content, bool hasScope) 25 | { 26 | _index = index; 27 | _content = content; 28 | _hasScope = hasScope; 29 | } 30 | } 31 | } -------------------------------------------------------------------------------- /src/CakeBoss.Agent/Aliases/AgentSettings.cs: -------------------------------------------------------------------------------- 1 | #region Using Statements 2 | using CakeBoss.Host; 3 | #endregion 4 | 5 | 6 | 7 | namespace CakeBoss.Agent 8 | { 9 | /// 10 | /// Settings used to configure the agent 11 | /// 12 | public class AgentSettings : HostSettings 13 | { 14 | #region Properties (3) 15 | /// 16 | /// Gets or sets if AWS termination time should be polled 17 | /// 18 | public bool EnableTerminationCheck { get; set; } 19 | 20 | /// 21 | /// Gets or sets if the nancy agent service should be enabled 22 | /// 23 | public bool EnableAPI { get; set; } 24 | 25 | /// 26 | /// Gets or sets if the scheduled tasks should be enabled 27 | /// 28 | public bool EnableScheduledTasks { get; set; } 29 | #endregion 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /src/Cake.Host/Scripting/Mono/MonoScriptEngine.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using Cake.Core.Diagnostics; 4 | using Cake.Core.Scripting; 5 | 6 | namespace Cake.Host.Scripting.Mono 7 | { 8 | public sealed class MonoScriptEngine : IScriptEngine 9 | { 10 | private readonly ICakeLog _log; 11 | 12 | public MonoScriptEngine(ICakeLog log) 13 | { 14 | _log = log; 15 | } 16 | 17 | public IScriptSession CreateSession(IScriptHost host, IDictionary arguments) 18 | { 19 | if (host == null) 20 | { 21 | throw new ArgumentNullException("host"); 22 | } 23 | if (arguments == null) 24 | { 25 | throw new ArgumentNullException("arguments"); 26 | } 27 | 28 | // Create the script session. 29 | _log.Debug("Creating script session..."); 30 | return new MonoScriptSession(host, _log); 31 | } 32 | } 33 | } -------------------------------------------------------------------------------- /src/CakeBoss.Host/Tasks/TaskRegistry.cs: -------------------------------------------------------------------------------- 1 | #region Using Statements 2 | using System; 3 | 4 | using Cake.Host.Scripting; 5 | 6 | using FluentScheduler; 7 | using FluentScheduler.Model; 8 | #endregion 9 | 10 | 11 | 12 | namespace CakeBoss.Host 13 | { 14 | public class TaskRegistry : Registry 15 | { 16 | #region Fields (1) 17 | private BuildScriptHost _Host; 18 | #endregion 19 | 20 | 21 | 22 | 23 | 24 | #region Constructor (1) 25 | public TaskRegistry(BuildScriptHost host) 26 | { 27 | if (host == null) 28 | { 29 | throw new ArgumentNullException("host"); 30 | } 31 | 32 | _Host = host; 33 | } 34 | #endregion 35 | 36 | 37 | 38 | 39 | 40 | #region Functions (1) 41 | public Schedule Schedule(string target) 42 | { 43 | return this.Schedule(() => _Host.RunTarget(target)); 44 | } 45 | #endregion 46 | } 47 | } -------------------------------------------------------------------------------- /src/Cake.Host/Commands/DryRunCommand.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using Cake.Core.Scripting; 3 | using Cake.Host.Scripting; 4 | 5 | namespace Cake.Host.Commands 6 | { 7 | /// 8 | /// A command that dry runs a build script. 9 | /// 10 | public sealed class DryRunCommand : ICommand 11 | { 12 | private readonly IScriptRunner _scriptRunner; 13 | private readonly DryRunScriptHost _host; 14 | 15 | // Delegate factory used by Autofac. 16 | public delegate DryRunCommand Factory(); 17 | 18 | public DryRunCommand(IScriptRunner scriptRunner, DryRunScriptHost host) 19 | { 20 | _scriptRunner = scriptRunner; 21 | _host = host; 22 | } 23 | 24 | public bool Execute(CakeOptions options) 25 | { 26 | if (options == null) 27 | { 28 | throw new ArgumentNullException("options"); 29 | } 30 | _scriptRunner.Run(_host, options.Script, options.Arguments); 31 | return true; 32 | } 33 | } 34 | } -------------------------------------------------------------------------------- /src/Cake.Host/Commands/BuildCommand.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using Cake.Core.Scripting; 3 | using Cake.Host.Scripting; 4 | 5 | namespace Cake.Host.Commands 6 | { 7 | /// 8 | /// A command that builds and runs a build script. 9 | /// 10 | public sealed class BuildCommand : ICommand 11 | { 12 | private readonly IScriptRunner _scriptRunner; 13 | private readonly BuildScriptHost _host; 14 | 15 | // Delegate factory used by Autofac. 16 | public delegate BuildCommand Factory(); 17 | 18 | public BuildCommand(IScriptRunner scriptRunner, BuildScriptHost host) 19 | { 20 | _scriptRunner = scriptRunner; 21 | _host = host; 22 | } 23 | 24 | public bool Execute(CakeOptions options) 25 | { 26 | if (options == null) 27 | { 28 | throw new ArgumentNullException("options"); 29 | } 30 | _scriptRunner.Run(_host, options.Script, options.Arguments); 31 | return true; 32 | } 33 | } 34 | } -------------------------------------------------------------------------------- /src/Cake.Host/Commands/DescriptionCommand.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using Cake.Core.Scripting; 3 | using Cake.Host.Scripting; 4 | 5 | namespace Cake.Host.Commands 6 | { 7 | /// 8 | /// A command that displays information about script tasks. 9 | /// 10 | public sealed class DescriptionCommand : ICommand 11 | { 12 | private readonly IScriptRunner _scriptRunner; 13 | private readonly DescriptionScriptHost _host; 14 | 15 | // Delegate factory used by Autofac. 16 | public delegate DescriptionCommand Factory(); 17 | 18 | public DescriptionCommand(IScriptRunner scriptRunner, DescriptionScriptHost host) 19 | { 20 | _scriptRunner = scriptRunner; 21 | _host = host; 22 | } 23 | 24 | public bool Execute(CakeOptions options) 25 | { 26 | if (options == null) 27 | { 28 | throw new ArgumentNullException("options"); 29 | } 30 | _scriptRunner.Run(_host, options.Script, options.Arguments); 31 | return true; 32 | } 33 | } 34 | } -------------------------------------------------------------------------------- /src/Cake.Host/Scripting/Mono/CodeGen/Parsing/ScriptToken.cs: -------------------------------------------------------------------------------- 1 | using System.Diagnostics; 2 | 3 | namespace Cake.Host.Scripting.Mono.CodeGen.Parsing 4 | { 5 | [DebuggerDisplay("{Value,nq} ({Type})")] 6 | public sealed class ScriptToken 7 | { 8 | private readonly ScriptTokenType _type; 9 | private readonly string _value; 10 | private readonly int _index; 11 | private readonly int _length; 12 | 13 | public ScriptTokenType Type 14 | { 15 | get { return _type; } 16 | } 17 | 18 | public string Value 19 | { 20 | get { return _value; } 21 | } 22 | 23 | public int Index 24 | { 25 | get { return _index; } 26 | } 27 | 28 | public int Length 29 | { 30 | get { return _length; } 31 | } 32 | 33 | public ScriptToken(ScriptTokenType type, string value, int index, int length) 34 | { 35 | _type = type; 36 | _value = value; 37 | _index = index; 38 | _length = length; 39 | } 40 | } 41 | } -------------------------------------------------------------------------------- /src/Cake.Host/Scripting/Roslyn/RoslynCodeGenerator.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using Cake.Core.Scripting; 3 | using Cake.Core.Scripting.CodeGen; 4 | 5 | namespace Cake.Host.Scripting.Roslyn 6 | { 7 | public sealed class RoslynCodeGenerator 8 | { 9 | public string Generate(Script script) 10 | { 11 | var usingDirectives = string.Join("\r\n", script.UsingAliasDirectives); 12 | var aliases = GetAliasCode(script); 13 | var code = string.Join("\r\n", script.Lines); 14 | return string.Join("\r\n", usingDirectives, aliases, code); 15 | } 16 | 17 | private static string GetAliasCode(Script context) 18 | { 19 | var result = new List(); 20 | foreach (var alias in context.Aliases) 21 | { 22 | result.Add(alias.Type == ScriptAliasType.Method 23 | ? MethodAliasGenerator.Generate(alias.Method) 24 | : PropertyAliasGenerator.Generate(alias.Method)); 25 | } 26 | return string.Join("\r\n", result); 27 | } 28 | } 29 | } -------------------------------------------------------------------------------- /src/CakeBoss.Host/Extensions/CakeContextExtensions.cs: -------------------------------------------------------------------------------- 1 | #region Using Statements 2 | using System; 3 | using System.Collections.Generic; 4 | 5 | using LightInject; 6 | using Cake.Core; 7 | #endregion 8 | 9 | 10 | 11 | namespace CakeBoss.Host 12 | { 13 | public static class CakeContextExtensions 14 | { 15 | #region Functions (1) 16 | public static IServiceContainer Container; 17 | #endregion 18 | 19 | 20 | 21 | 22 | 23 | #region Functions (3) 24 | public static IServiceContainer GetContainer(this ICakeContext context) 25 | { 26 | return Container; 27 | } 28 | 29 | public static TService GetInstance(this ICakeContext context) 30 | { 31 | return context.GetContainer().GetInstance(); 32 | } 33 | 34 | public static TService GetInstance(this ICakeContext context, string serviceName) 35 | { 36 | return context.GetContainer().GetInstance(serviceName); 37 | } 38 | #endregion 39 | } 40 | } -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Misc folders 2 | [Bb]in/ 3 | [Oo]bj/ 4 | [Tt]emp/ 5 | [Pp]ackages/ 6 | /[Bb]uild/ 7 | *.sln.ide/ 8 | 9 | # Build related 10 | build/ 11 | tools/ 12 | test/tools/ 13 | 14 | 15 | 16 | ## Ignore Visual Studio temporary files, build results, and 17 | ## files generated by popular Visual Studio add-ons. 18 | 19 | # User-specific files 20 | *.suo 21 | *.user 22 | *.sln.docstates 23 | *.userprefs 24 | *.GhostDoc.xml 25 | *StyleCop.Cache 26 | 27 | # Build results 28 | [Dd]ebug/ 29 | [Rr]elease/ 30 | x64/ 31 | *_i.c 32 | *_p.c 33 | *.ilk 34 | *.meta 35 | *.obj 36 | *.pch 37 | *.pdb 38 | *.pgc 39 | *.pgd 40 | *.rsp 41 | *.sbr 42 | *.tlb 43 | *.tli 44 | *.tlh 45 | *.tmp 46 | *.log 47 | *.vspscc 48 | *.vssscc 49 | .builds 50 | 51 | # Visual Studio profiler 52 | *.psess 53 | *.vsp 54 | *.vspx 55 | 56 | # ReSharper is a .NET coding add-in 57 | _ReSharper* 58 | 59 | # NCrunch 60 | *.ncrunch* 61 | .*crunch*.local.xml 62 | _NCrunch_* 63 | 64 | 65 | 66 | # Visual Studio Directory 67 | src/.vs/ 68 | 69 | # NuGet Packages Directory 70 | src/packages/ 71 | 72 | # mstest test results 73 | src/TestResults/ 74 | 75 | 76 | 77 | # Windows 78 | Thumbs.db 79 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2015 - 2016 Phillip Sharpe 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy of 6 | this software and associated documentation files (the "Software"), to deal in 7 | the Software without restriction, including without limitation the rights to 8 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 9 | the Software, and to permit persons to whom the Software is furnished to do so, 10 | subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 17 | FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 18 | COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 19 | IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 20 | CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -------------------------------------------------------------------------------- /src/CakeBoss.Host/Auth/AuthenticationService.cs: -------------------------------------------------------------------------------- 1 | #region Using Statements 2 | using System; 3 | #endregion 4 | 5 | 6 | 7 | namespace CakeBoss.Host 8 | { 9 | public class AuthenticationService : IAuthenticationService 10 | { 11 | #region Fields (1) 12 | private HostSettings _Settings; 13 | #endregion 14 | 15 | 16 | 17 | 18 | 19 | #region Constructor (1) 20 | public AuthenticationService(HostSettings settings) 21 | { 22 | if (settings == null) 23 | { 24 | throw new ArgumentNullException("settings"); 25 | } 26 | 27 | _Settings = settings; 28 | } 29 | #endregion 30 | 31 | 32 | 33 | 34 | 35 | #region Functions (2) 36 | public bool ValidUser(string username, string password) 37 | { 38 | return _Settings.ContainsUser(username, password); 39 | } 40 | 41 | public bool ValidApiKey(string apiKey) 42 | { 43 | return _Settings.ContainsApiKey(apiKey); 44 | } 45 | #endregion 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /src/CakeBoss.Agent/Nancy/ServiceModule.cs: -------------------------------------------------------------------------------- 1 | #region Using Statements 2 | using System; 3 | 4 | using Nancy; 5 | using Nancy.Security; 6 | #endregion 7 | 8 | 9 | 10 | namespace CakeBoss.Agent 11 | { 12 | public class ServiceModule : NancyModule 13 | { 14 | #region Fields (1) 15 | private IAgentService _Service; 16 | #endregion 17 | 18 | 19 | 20 | 21 | 22 | #region Constructors (1) 23 | public ServiceModule(IAgentService service) 24 | : base("/agent") 25 | { 26 | if (service == null) 27 | { 28 | throw new ArgumentNullException("service"); 29 | } 30 | 31 | _Service = service; 32 | 33 | this.RequiresAuthentication(); 34 | 35 | 36 | 37 | Get["/current"] = x => 38 | { 39 | return _Service.CurrentTask; 40 | }; 41 | 42 | Post["/run/{target}"] = x => 43 | { 44 | return _Service.RunTarget(x.target, false); 45 | }; 46 | } 47 | #endregion 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /src/CakeBoss.Host/Console/ConsoleOutput.cs: -------------------------------------------------------------------------------- 1 | #region Using Statements 2 | using System; 3 | using System.Collections.Generic; 4 | 5 | using Cake.Core.Diagnostics; 6 | using Cake.Core.IO; 7 | #endregion 8 | 9 | 10 | 11 | namespace CakeBoss.Host 12 | { 13 | /// 14 | /// Output from the cake console 15 | /// 16 | public sealed class ConsoleOutput 17 | { 18 | #region Constructor (1) 19 | public ConsoleOutput(string text, ConsoleColor color) 20 | { 21 | this.Text = text; 22 | this.ForegroundColor = color; 23 | } 24 | #endregion 25 | 26 | 27 | 28 | 29 | 30 | #region Properties (2) 31 | /// 32 | /// Gets or sets the text 33 | /// 34 | /// The text. 35 | public string Text { get; set; } 36 | 37 | /// 38 | /// Gets or sets the foreground color. 39 | /// 40 | /// The foreground color. 41 | public ConsoleColor ForegroundColor { get; set; } 42 | #endregion 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /src/Cake.Host/Commands/ICommandFactory.cs: -------------------------------------------------------------------------------- 1 | namespace Cake.Host.Commands 2 | { 3 | /// 4 | /// Represents a command factory. 5 | /// 6 | public interface ICommandFactory 7 | { 8 | /// 9 | /// Creates the build command. 10 | /// 11 | /// The build command. 12 | ICommand CreateBuildCommand(); 13 | 14 | /// 15 | /// Creates the description command. 16 | /// 17 | /// The description command. 18 | ICommand CreateDescriptionCommand(); 19 | 20 | /// 21 | /// Creates the dry run command. 22 | /// 23 | /// The dry run command. 24 | ICommand CreateDryRunCommand(); 25 | 26 | /// 27 | /// Creates the help command. 28 | /// 29 | /// The help command. 30 | ICommand CreateHelpCommand(); 31 | 32 | /// 33 | /// Creates the version command. 34 | /// 35 | /// The version command. 36 | ICommand CreateVersionCommand(); 37 | } 38 | } -------------------------------------------------------------------------------- /src/CakeBoss.Agent/App.config: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /src/Cake.Host/Diagnostics/Formatting/PropertyToken.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Globalization; 3 | 4 | namespace Cake.Host.Diagnostics.Formatting 5 | { 6 | public sealed class PropertyToken : FormatToken 7 | { 8 | private readonly int _position; 9 | private readonly string _format; 10 | 11 | public string Format 12 | { 13 | get { return _format; } 14 | } 15 | 16 | public int Position 17 | { 18 | get { return _position; } 19 | } 20 | 21 | public PropertyToken(int position, string format) 22 | { 23 | _position = position; 24 | _format = format; 25 | } 26 | 27 | public override string Render(object[] args) 28 | { 29 | var value = args[_position]; 30 | if (!string.IsNullOrWhiteSpace(_format)) 31 | { 32 | var formattable = value as IFormattable; 33 | if (formattable != null) 34 | { 35 | return formattable.ToString(_format, CultureInfo.InvariantCulture); 36 | } 37 | } 38 | return (value == null) 39 | ? "[NULL]" 40 | : value.ToString(); 41 | } 42 | } 43 | } -------------------------------------------------------------------------------- /nuspec/Cake.CakeBoss.nuspec: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Cake.CakeBoss 5 | 0.0.0 6 | Phillip Sharpe 7 | Phillip Sharpe 8 | Cake.CakeBoss 9 | Cake Build addon for calling CakeBoss agents. 10 | CakeBoss addon for cake build. 11 | https://github.com/SharpeRAD/CakeBoss/LICENSE 12 | https://github.com/SharpeRAD/CakeBoss 13 | https://cdn.jsdelivr.net/gh/cake-contrib/graphics/png/cake-contrib-medium.png 14 | false 15 | Copyright (c) Phillip Sharpe 2015 16 | Initial Release 17 | Cake Script Build DevOpps 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | -------------------------------------------------------------------------------- /src/CakeBoss.Agent/Nancy/ServiceStartup.cs: -------------------------------------------------------------------------------- 1 | #region Using Statements 2 | using Nancy; 3 | using Nancy.Responses; 4 | using Nancy.Bootstrapper; 5 | using Nancy.Authentication.Basic; 6 | 7 | using Cake.Core; 8 | using Cake.Core.Diagnostics; 9 | #endregion 10 | 11 | 12 | 13 | namespace CakeBoss.Agent 14 | { 15 | public class ServiceStaartup : IApplicationStartup 16 | { 17 | #region Functions (3) 18 | public void Initialize(IPipelines pipelines) 19 | { 20 | pipelines.EnableBasicAuthentication(new BasicAuthenticationConfiguration(Program.Container.GetInstance(), "CakeBoss", UserPromptBehaviour.NonAjax)); 21 | 22 | pipelines.OnError.AddItemToEndOfPipeline((context, exception) => 23 | { 24 | //Log Error 25 | ICakeLog log = Program.Container.GetInstance(); 26 | 27 | log.Error(exception.Message); 28 | 29 | 30 | 31 | //Return Response 32 | Response response = new JsonResponse(exception.Message, Program.Container.GetInstance()); 33 | 34 | response.StatusCode = HttpStatusCode.InternalServerError; 35 | 36 | return response; 37 | }); 38 | } 39 | #endregion 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /src/CakeBoss.Host/Nancy/UserValidator.cs: -------------------------------------------------------------------------------- 1 | #region Using Statements 2 | using System; 3 | 4 | using Nancy; 5 | using Nancy.Security; 6 | using Nancy.Authentication.Basic; 7 | #endregion 8 | 9 | 10 | 11 | namespace CakeBoss.Host 12 | { 13 | public class UserValidator : IUserValidator 14 | { 15 | #region Fields (1) 16 | private IAuthenticationService _AuthenticationService; 17 | #endregion 18 | 19 | 20 | 21 | 22 | 23 | #region Constructor (1) 24 | public UserValidator(IAuthenticationService authenticationService) 25 | { 26 | if (authenticationService == null) 27 | { 28 | throw new ArgumentNullException("authenticationService"); 29 | } 30 | 31 | _AuthenticationService = authenticationService; 32 | } 33 | #endregion 34 | 35 | 36 | 37 | 38 | 39 | #region Functions (1) 40 | public IUserIdentity Validate(string username, string password) 41 | { 42 | if (_AuthenticationService.ValidUser(username, password)) 43 | { 44 | return new UserIdentity(username); 45 | } 46 | else 47 | { 48 | return null; 49 | } 50 | } 51 | #endregion 52 | } 53 | } -------------------------------------------------------------------------------- /src/CakeBoss.Agent/Aliases/TerminationAliases.cs: -------------------------------------------------------------------------------- 1 | #region Using Statements 2 | using Cake.Core; 3 | using Cake.Core.Annotations; 4 | using Cake.Core.Diagnostics; 5 | 6 | using CakeBoss.Host; 7 | #endregion 8 | 9 | 10 | 11 | namespace CakeBoss.Agent 12 | { 13 | [CakeAliasCategory("CakeBoss")] 14 | public static class TerminationAliases 15 | { 16 | /// 17 | /// Starts the termination service 18 | /// 19 | /// The context. 20 | [CakeMethodAlias] 21 | [CakeAliasCategory("Termination")] 22 | public static void StartTerminationCheck(this ICakeContext context) 23 | { 24 | context.GetContainer().GetInstance().Enabled = true; 25 | 26 | context.Log.Information("Termination service started."); 27 | } 28 | 29 | /// 30 | /// Stops the termination service 31 | /// 32 | /// The context. 33 | [CakeMethodAlias] 34 | [CakeAliasCategory("Termination")] 35 | public static void StopTerminationCheck(this ICakeContext context) 36 | { 37 | context.GetContainer().GetInstance().Enabled = false; 38 | 39 | context.Log.Information("Termination service stopped."); 40 | } 41 | } 42 | } 43 | 44 | -------------------------------------------------------------------------------- /src/CakeBoss.Host/Aliases/HostAliases.cs: -------------------------------------------------------------------------------- 1 | #region Using Statements 2 | using System; 3 | using System.Collections.ObjectModel; 4 | 5 | using Cake.Core; 6 | using Cake.Core.IO; 7 | using Cake.Core.Annotations; 8 | using Cake.Core.Diagnostics; 9 | 10 | using LightInject; 11 | #endregion 12 | 13 | 14 | 15 | namespace CakeBoss.Host 16 | { 17 | [CakeAliasCategory("CakeBoss")] 18 | public static class HostAliases 19 | { 20 | /// 21 | /// Starts a Nuget server using the specified information. 22 | /// 23 | /// The context. 24 | /// The Nuget server settings. 25 | [CakeMethodAlias] 26 | [CakeAliasCategory("Host")] 27 | public static void ConfigureHost(this ICakeContext context, HostSettings settings) 28 | { 29 | HostSettings instance = context.GetContainer().GetInstance(); 30 | 31 | foreach (User user in settings.Users) 32 | { 33 | instance.AddUser(user.Username, user.Password); 34 | } 35 | 36 | foreach (string key in settings.ApiKeys) 37 | { 38 | instance.AddApiKey(key); 39 | } 40 | 41 | instance.Host = settings.Host; 42 | instance.Port = settings.Port; 43 | instance.Url = settings.Url; 44 | 45 | context.Log.Information("Host configured."); 46 | } 47 | } 48 | } 49 | 50 | -------------------------------------------------------------------------------- /src/Cake.Host/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.CompilerServices; 3 | using System.Runtime.InteropServices; 4 | 5 | // General Information about an assembly is controlled through the following 6 | // set of attributes. Change these attribute values to modify the information 7 | // associated with an assembly. 8 | [assembly: AssemblyTitle("Host")] 9 | [assembly: AssemblyDescription("")] 10 | [assembly: AssemblyConfiguration("")] 11 | [assembly: AssemblyCompany("")] 12 | [assembly: AssemblyProduct("Host")] 13 | [assembly: AssemblyCopyright("Copyright © 2015")] 14 | [assembly: AssemblyTrademark("")] 15 | [assembly: AssemblyCulture("")] 16 | 17 | // Setting ComVisible to false makes the types in this assembly not visible 18 | // to COM components. If you need to access a type in this assembly from 19 | // COM, set the ComVisible attribute to true on that type. 20 | [assembly: ComVisible(false)] 21 | 22 | // The following GUID is for the ID of the typelib if this project is exposed to COM 23 | [assembly: Guid("206f12ed-5ffa-4333-a5a9-31c142648ac1")] 24 | 25 | // Version information for an assembly consists of the following four values: 26 | // 27 | // Major Version 28 | // Minor Version 29 | // Build Number 30 | // Revision 31 | // 32 | // You can specify all the values or you can default the Build and Revision Numbers 33 | // by using the '*' as shown below: 34 | // [assembly: AssemblyVersion("1.0.*")] 35 | [assembly: AssemblyVersion("1.0.0.0")] 36 | [assembly: AssemblyFileVersion("1.0.0.0")] 37 | -------------------------------------------------------------------------------- /src/CakeBoss.Agent.Tests/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.CompilerServices; 3 | using System.Runtime.InteropServices; 4 | 5 | // General Information about an assembly is controlled through the following 6 | // set of attributes. Change these attribute values to modify the information 7 | // associated with an assembly. 8 | [assembly: AssemblyTitle("Tests")] 9 | [assembly: AssemblyDescription("")] 10 | [assembly: AssemblyConfiguration("")] 11 | [assembly: AssemblyCompany("")] 12 | [assembly: AssemblyProduct("Tests")] 13 | [assembly: AssemblyCopyright("Copyright © 2015")] 14 | [assembly: AssemblyTrademark("")] 15 | [assembly: AssemblyCulture("")] 16 | 17 | // Setting ComVisible to false makes the types in this assembly not visible 18 | // to COM components. If you need to access a type in this assembly from 19 | // COM, set the ComVisible attribute to true on that type. 20 | [assembly: ComVisible(false)] 21 | 22 | // The following GUID is for the ID of the typelib if this project is exposed to COM 23 | [assembly: Guid("86e04045-fe0d-4eb4-85c1-8b7792b4c4e3")] 24 | 25 | // Version information for an assembly consists of the following four values: 26 | // 27 | // Major Version 28 | // Minor Version 29 | // Build Number 30 | // Revision 31 | // 32 | // You can specify all the values or you can default the Build and Revision Numbers 33 | // by using the '*' as shown below: 34 | // [assembly: AssemblyVersion("1.0.*")] 35 | [assembly: AssemblyVersion("1.0.0.0")] 36 | [assembly: AssemblyFileVersion("1.0.0.0")] 37 | -------------------------------------------------------------------------------- /src/CakeBoss.Host/Auth/HostSettings.cs: -------------------------------------------------------------------------------- 1 | #region Using Statements 2 | using System; 3 | using System.Collections.Generic; 4 | 5 | using Cake.Core.IO; 6 | #endregion 7 | 8 | 9 | 10 | namespace CakeBoss.Host 11 | { 12 | public class HostSettings 13 | { 14 | #region Fields (1) 15 | private string _Url; 16 | #endregion 17 | 18 | 19 | 20 | 21 | 22 | #region Constructor (1) 23 | public HostSettings() 24 | { 25 | this.Users = new List(); 26 | this.ApiKeys = new List(); 27 | 28 | this.Host = "localhost"; 29 | this.Port = 8080; 30 | 31 | _Url = ""; 32 | } 33 | #endregion 34 | 35 | 36 | 37 | 38 | 39 | #region Properties (4) 40 | public IList Users { get; set; } 41 | 42 | public IList ApiKeys { get; set; } 43 | 44 | 45 | 46 | public string Host { get; set; } 47 | 48 | public int Port { get; set; } 49 | 50 | 51 | 52 | public string Url 53 | { 54 | set 55 | { 56 | _Url = value; 57 | } 58 | get 59 | { 60 | if (!String.IsNullOrEmpty(_Url)) 61 | { 62 | return _Url; 63 | } 64 | else 65 | { 66 | return "http://" + this.Host + ":" + this.Port.ToString(); 67 | } 68 | } 69 | } 70 | #endregion 71 | } 72 | } -------------------------------------------------------------------------------- /src/CakeBoss.Agent.Tests/Config/Startup.cs: -------------------------------------------------------------------------------- 1 | #region Using Statements 2 | using System; 3 | 4 | using LightInject; 5 | using Nancy.Hosting.Self; 6 | 7 | using CakeBoss.Agent; 8 | using CakeBoss.Host; 9 | #endregion 10 | 11 | 12 | 13 | namespace CakeBoss.Agent.Tests 14 | { 15 | public static class Startup 16 | { 17 | #region Fields (2) 18 | public static IServiceContainer Container = null; 19 | public static NancyHost Host = null; 20 | #endregion 21 | 22 | 23 | 24 | 25 | 26 | #region Functions (2) 27 | public static void CreateContainer() 28 | { 29 | if (Container == null) 30 | { 31 | var container = new ServiceContainer(); 32 | 33 | container.EnableAnnotatedPropertyInjection(); 34 | 35 | container.RegisterFrom(); 36 | container.RegisterFrom(); 37 | 38 | Container = container; 39 | } 40 | } 41 | 42 | public static void ConfigureHost() 43 | { 44 | if (Host == null) 45 | { 46 | Host = new NancyHost(new Uri("http://localhost:2001"), new UnitTestBootstrapper(), new HostConfiguration() 47 | { 48 | UrlReservations = new UrlReservations() 49 | { 50 | CreateAutomatically = true 51 | } 52 | }); 53 | 54 | Host.Start(); 55 | } 56 | } 57 | #endregion 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /src/CakeBoss.Agent/Nancy/ServiceBootstrapper.cs: -------------------------------------------------------------------------------- 1 | #region Using Statements 2 | using LightInject; 3 | using LightInject.Nancy; 4 | 5 | using Nancy; 6 | using Nancy.Responses; 7 | using Nancy.Bootstrapper; 8 | using Nancy.Authentication.Basic; 9 | 10 | using Cake.Core; 11 | using Cake.Core.Diagnostics; 12 | #endregion 13 | 14 | 15 | 16 | namespace CakeBoss.Agent 17 | { 18 | public class ServiceBootstrapper : LightInjectNancyBootstrapper 19 | { 20 | #region Functions (3) 21 | protected override IServiceContainer GetServiceContainer() 22 | { 23 | return Program.Container; 24 | } 25 | 26 | 27 | 28 | /* 29 | protected override void ApplicationStartup(IServiceContainer container, IPipelines pipelines) 30 | { 31 | base.ApplicationStartup(container, pipelines); 32 | 33 | pipelines.EnableBasicAuthentication(new BasicAuthenticationConfiguration(container.GetInstance(), "CakeBoss", UserPromptBehaviour.NonAjax)); 34 | 35 | pipelines.OnError.AddItemToEndOfPipeline((context, exception) => 36 | { 37 | //Log Error 38 | ICakeLog log = container.GetInstance(); 39 | 40 | log.Error(exception.Message); 41 | 42 | 43 | 44 | //Return Response 45 | Response response = new JsonResponse(exception.Message, container.GetInstance()); 46 | 47 | response.StatusCode = HttpStatusCode.InternalServerError; 48 | 49 | return response; 50 | }); 51 | }*/ 52 | #endregion 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /src/Cake.Host/Scripting/Roslyn/RoslynScriptEngine.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using Cake.Core.Diagnostics; 4 | using Cake.Core.Scripting; 5 | using Cake.Host.Scripting.Roslyn.Nightly; 6 | using Cake.Host.Scripting.Roslyn.Stable; 7 | 8 | namespace Cake.Host.Scripting.Roslyn 9 | { 10 | public sealed class RoslynScriptEngine : IScriptEngine 11 | { 12 | private readonly RoslynScriptSessionFactory _stableFactory; 13 | private readonly RoslynNightlyScriptSessionFactory _nightlyFactory; 14 | private readonly ICakeLog _log; 15 | 16 | public RoslynScriptEngine( 17 | RoslynScriptSessionFactory stableFactory, 18 | RoslynNightlyScriptSessionFactory nightlyFactory, 19 | ICakeLog log) 20 | { 21 | _nightlyFactory = nightlyFactory; 22 | _stableFactory = stableFactory; 23 | _log = log; 24 | } 25 | 26 | public IScriptSession CreateSession(IScriptHost host, IDictionary arguments) 27 | { 28 | if (arguments == null) 29 | { 30 | throw new ArgumentNullException("arguments"); 31 | } 32 | 33 | // Create the script session. 34 | _log.Debug("Creating script session..."); 35 | 36 | // Are we using the experimental bits? 37 | if (arguments.ContainsKey("experimental")) 38 | { 39 | // Use the nightly build. 40 | _log.Debug("Using prerelease build of Roslyn."); 41 | return _nightlyFactory.CreateSession(host); 42 | } 43 | 44 | // Use the stable build. 45 | return _stableFactory.CreateSession(host); 46 | } 47 | } 48 | } -------------------------------------------------------------------------------- /src/Cake.Host/Scripting/BuildScriptHost.cs: -------------------------------------------------------------------------------- 1 | using Cake.Core; 2 | using Cake.Core.Diagnostics; 3 | using Cake.Core.Scripting; 4 | 5 | namespace Cake.Host.Scripting 6 | { 7 | /// 8 | /// The script host used to execute Cake.Host scripts. 9 | /// 10 | public sealed class BuildScriptHost : ScriptHost 11 | { 12 | private readonly ICakeReportPrinter _reportPrinter; 13 | private readonly ICakeLog _log; 14 | 15 | /// 16 | /// Initializes a new instance of the class. 17 | /// 18 | /// The engine. 19 | /// The context. 20 | /// The report printer. 21 | /// The log. 22 | public BuildScriptHost( 23 | ICakeEngine engine, 24 | ICakeContext context, 25 | ICakeReportPrinter reportPrinter, 26 | ICakeLog log) : base(engine, context) 27 | { 28 | _reportPrinter = reportPrinter; 29 | _log = log; 30 | } 31 | 32 | /// 33 | /// Runs the specified target. 34 | /// 35 | /// The target to run. 36 | /// The resulting report. 37 | public override CakeReport RunTarget(string target) 38 | { 39 | var strategy = new DefaultExecutionStrategy(_log); 40 | var report = Engine.RunTarget(Context, strategy, target); 41 | if (report != null && !report.IsEmpty) 42 | { 43 | _reportPrinter.Write(report); 44 | } 45 | return report; 46 | } 47 | } 48 | } -------------------------------------------------------------------------------- /src/CakeBoss.Host/Extensions/HostSettingsExtensions.cs: -------------------------------------------------------------------------------- 1 | #region Using Statements 2 | using System; 3 | using System.Linq; 4 | #endregion 5 | 6 | 7 | 8 | namespace CakeBoss.Host 9 | { 10 | public static class HostSettingsExtensions 11 | { 12 | #region Functions (6) 13 | public static T AddUser(this T settings, string username, string password) where T : HostSettings 14 | { 15 | settings.Users.Add(new User(username, password)); 16 | 17 | return settings; 18 | } 19 | 20 | public static HostSettings AddApiKey(this T settings, string key) where T : HostSettings 21 | { 22 | settings.ApiKeys.Add(key); 23 | 24 | return settings; 25 | } 26 | 27 | 28 | 29 | public static bool ContainsUser(this T settings, string username, string password) where T : HostSettings 30 | { 31 | return (settings.Users.FirstOrDefault(u => u.Username == username && u.Password == password) != null); 32 | } 33 | 34 | public static bool ContainsApiKey(this T settings, string apiKey) where T : HostSettings 35 | { 36 | return settings.ApiKeys.Contains(apiKey); 37 | } 38 | 39 | 40 | 41 | public static T SetUrl(this T settings, string url) where T : HostSettings 42 | { 43 | settings.Url = url; 44 | 45 | return settings; 46 | } 47 | 48 | public static T SetPort(this T settings, int port) where T : HostSettings 49 | { 50 | settings.Port = port; 51 | 52 | return settings; 53 | } 54 | #endregion 55 | } 56 | } -------------------------------------------------------------------------------- /src/Cake.Host/Scripting/Mono/CodeGen/MonoScriptProcessor.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using Cake.Core; 4 | using Cake.Core.Scripting; 5 | using Cake.Host.Scripting.Mono.CodeGen.Parsing; 6 | 7 | namespace Cake.Host.Scripting.Mono.CodeGen 8 | { 9 | public static class MonoScriptProcessor 10 | { 11 | public static Script Process(Script script, out IReadOnlyList blocks) 12 | { 13 | var lines = new List(); 14 | var result = new List(); 15 | foreach (var codeBlock in ParseBlocks(script)) 16 | { 17 | if (codeBlock.HasScope) 18 | { 19 | result.Add(codeBlock); 20 | } 21 | else 22 | { 23 | lines.AddRange(codeBlock.Content.SplitLines()); 24 | } 25 | } 26 | blocks = result; // Assign the parsed blocks. 27 | return new Script(script.Namespaces, lines, script.Aliases, script.UsingAliasDirectives); 28 | } 29 | 30 | private static IEnumerable ParseBlocks(Script script) 31 | { 32 | var code = string.Join(Environment.NewLine, script.Lines); 33 | using (var parser = new ScriptParser(code)) 34 | { 35 | var result = new List(); 36 | while (true) 37 | { 38 | var block = parser.ParseNext(); 39 | if (block == null) 40 | { 41 | break; 42 | } 43 | result.Add(block); 44 | } 45 | return result; 46 | } 47 | } 48 | } 49 | } -------------------------------------------------------------------------------- /src/Cake.Host/Scripting/DryRunExecutionStrategy.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using Cake.Core; 3 | using Cake.Core.Diagnostics; 4 | 5 | namespace Cake.Host.Scripting 6 | { 7 | public sealed class DryRunExecutionStrategy : IExecutionStrategy 8 | { 9 | private readonly ICakeLog _log; 10 | private int _counter; 11 | 12 | public DryRunExecutionStrategy(ICakeLog log) 13 | { 14 | if (log == null) 15 | { 16 | throw new ArgumentNullException("log"); 17 | } 18 | _log = log; 19 | _counter = 1; 20 | } 21 | 22 | public void PerformSetup(Action action) 23 | { 24 | } 25 | 26 | public void PerformTeardown(Action action) 27 | { 28 | } 29 | 30 | public void Execute(CakeTask task, ICakeContext context) 31 | { 32 | if (task != null) 33 | { 34 | _log.Information("{0}. {1}", _counter, task.Name); 35 | _counter++; 36 | } 37 | } 38 | 39 | public void Skip(CakeTask task) 40 | { 41 | } 42 | 43 | public void ReportErrors(Action action, Exception exception) 44 | { 45 | } 46 | 47 | public void HandleErrors(Action action, Exception exception) 48 | { 49 | } 50 | 51 | public void InvokeFinally(Action action) 52 | { 53 | } 54 | 55 | public void PerformTaskSetup(Action action, ICakeContext context, ITaskSetupContext setupContext) 56 | { 57 | } 58 | 59 | public void PerformTaskTeardown(Action action, ICakeContext context, ITaskTeardownContext teardownContext) 60 | { 61 | } 62 | } 63 | } -------------------------------------------------------------------------------- /src/Cake.Host/packages.config: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /src/Cake.Host/Commands/CommandFactory.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using Cake.Core.Scripting; 3 | using Cake.Host.Scripting; 4 | 5 | namespace Cake.Host.Commands 6 | { 7 | public class CommandFactory : ICommandFactory 8 | { 9 | private readonly BuildCommand _buildCommandFactory; 10 | private readonly DescriptionCommand _descriptionCommandFactory; 11 | private readonly DryRunCommand _dryRunCommandFactory; 12 | private readonly HelpCommand _helpCommandFactory; 13 | private readonly VersionCommand _versionCommandFactory; 14 | 15 | public CommandFactory( 16 | BuildCommand buildCommandFactory, 17 | DescriptionCommand descriptionCommandFactory, 18 | DryRunCommand dryRunCommandFactory, 19 | HelpCommand helpCommandFactory, 20 | VersionCommand versionCommandFactory) 21 | { 22 | _buildCommandFactory = buildCommandFactory; 23 | _descriptionCommandFactory = descriptionCommandFactory; 24 | _dryRunCommandFactory = dryRunCommandFactory; 25 | _helpCommandFactory = helpCommandFactory; 26 | _versionCommandFactory = versionCommandFactory; 27 | } 28 | 29 | public ICommand CreateBuildCommand() 30 | { 31 | return _buildCommandFactory; 32 | } 33 | 34 | public ICommand CreateDescriptionCommand() 35 | { 36 | return _descriptionCommandFactory; 37 | } 38 | 39 | public ICommand CreateDryRunCommand() 40 | { 41 | return _dryRunCommandFactory; 42 | } 43 | 44 | public ICommand CreateHelpCommand() 45 | { 46 | return _helpCommandFactory; 47 | } 48 | 49 | public ICommand CreateVersionCommand() 50 | { 51 | return _versionCommandFactory; 52 | } 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /src/Cake.Host/Scripting/DryRunScriptHost.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using Cake.Core; 3 | using Cake.Core.Diagnostics; 4 | using Cake.Core.Scripting; 5 | 6 | namespace Cake.Host.Scripting 7 | { 8 | /// 9 | /// The script host used to dry run Cake.Host scripts. 10 | /// 11 | public sealed class DryRunScriptHost : ScriptHost 12 | { 13 | private readonly ICakeLog _log; 14 | 15 | /// 16 | /// Initializes a new instance of the class. 17 | /// 18 | /// The engine. 19 | /// The context. 20 | /// The log. 21 | public DryRunScriptHost(ICakeEngine engine, ICakeContext context, ICakeLog log) 22 | : base(engine, context) 23 | { 24 | if (log == null) 25 | { 26 | throw new ArgumentNullException("log"); 27 | } 28 | _log = log; 29 | } 30 | 31 | /// 32 | /// Runs the specified target. 33 | /// 34 | /// The target to run. 35 | /// The resulting report. 36 | public override CakeReport RunTarget(string target) 37 | { 38 | _log.Information("Performing dry run..."); 39 | _log.Information("Target is: {0}", target); 40 | _log.Information(string.Empty); 41 | 42 | var strategy = new DryRunExecutionStrategy(_log); 43 | var result = Engine.RunTarget(Context, strategy, target); 44 | 45 | _log.Information(string.Empty); 46 | _log.Information("This was a dry run."); 47 | _log.Information("No tasks were actually executed."); 48 | 49 | return result; 50 | } 51 | } 52 | } -------------------------------------------------------------------------------- /src/CakeBoss.Agent.Tests/Config/UnitTestBootstrapper.cs: -------------------------------------------------------------------------------- 1 | #region Using Statements 2 | using LightInject; 3 | using LightInject.Nancy; 4 | 5 | using Nancy; 6 | using Nancy.Responses; 7 | using Nancy.Bootstrapper; 8 | using Nancy.Authentication.Basic; 9 | 10 | using Cake.Core; 11 | using Cake.Core.Diagnostics; 12 | #endregion 13 | 14 | 15 | 16 | namespace CakeBoss.Agent.Tests 17 | { 18 | public class UnitTestBootstrapper : LightInjectNancyBootstrapper 19 | { 20 | #region Functions (3) 21 | protected override IServiceContainer GetServiceContainer() 22 | { 23 | return Startup.Container; 24 | } 25 | 26 | protected override void ConfigureApplicationContainer(IServiceContainer container) 27 | { 28 | base.ConfigureApplicationContainer(container); 29 | } 30 | 31 | 32 | 33 | protected override void ApplicationStartup(IServiceContainer container, IPipelines pipelines) 34 | { 35 | base.ApplicationStartup(container, pipelines); 36 | 37 | pipelines.EnableBasicAuthentication(new BasicAuthenticationConfiguration(container.GetInstance(), "CakeBoss", UserPromptBehaviour.NonAjax)); 38 | 39 | pipelines.OnError.AddItemToEndOfPipeline((context, exception) => 40 | { 41 | //Log Error 42 | ICakeLog log = container.GetInstance(); 43 | 44 | log.Error(exception.Message); 45 | 46 | 47 | 48 | //Return Response 49 | Response response = new JsonResponse(exception.Message, container.GetInstance()); 50 | 51 | response.StatusCode = HttpStatusCode.InternalServerError; 52 | 53 | return response; 54 | }); 55 | } 56 | #endregion 57 | } 58 | } -------------------------------------------------------------------------------- /src/Cake.Host/Arguments/VerbosityParser.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using Cake.Core.Diagnostics; 4 | 5 | namespace Cake.Host.Arguments 6 | { 7 | /// 8 | /// Responsible for parsing . 9 | /// 10 | public sealed class VerbosityParser 11 | { 12 | private readonly Dictionary _lookup; 13 | 14 | /// 15 | /// Initializes a new instance of the class. 16 | /// 17 | public VerbosityParser() 18 | { 19 | _lookup = new Dictionary(StringComparer.OrdinalIgnoreCase) 20 | { 21 | { "q", Verbosity.Quiet }, 22 | { "quiet", Verbosity.Quiet }, 23 | { "m", Verbosity.Minimal }, 24 | { "minimal", Verbosity.Minimal }, 25 | { "n", Verbosity.Normal }, 26 | { "normal", Verbosity.Normal }, 27 | { "v", Verbosity.Verbose }, 28 | { "verbose", Verbosity.Verbose }, 29 | { "d", Verbosity.Diagnostic }, 30 | { "diagnostic", Verbosity.Diagnostic } 31 | }; 32 | } 33 | 34 | /// 35 | /// Parses the provided string to a . 36 | /// 37 | /// The string to parse. 38 | /// The verbosity. 39 | public Verbosity Parse(string value) 40 | { 41 | Verbosity verbosity; 42 | if (_lookup.TryGetValue(value, out verbosity)) 43 | { 44 | return verbosity; 45 | } 46 | const string format = "The value '{0}' is not a valid verbosity."; 47 | var message = string.Format(format, value ?? string.Empty); 48 | throw new InvalidOperationException(message); 49 | } 50 | } 51 | } -------------------------------------------------------------------------------- /ReleaseNotes.md: -------------------------------------------------------------------------------- 1 | ### New in 0.1.5 (Released 2016/01/29) 2 | * Update cake references 3 | * Seperate Termination and Api aliases from main config alias 4 | * Add "StopSchedules" alias 5 | * Add "RestartAgent" and "ReconfigureAgent" aliases 6 | * Check for blank command line target argument 7 | 8 | ### New in 0.1.4 (Released 2016/01/21) 9 | * Simplify build script file copying 10 | * Add extra checks for nuget.exe 11 | * Fix bug in target commaned line 12 | * Add deploy.bat as an example use of target 13 | 14 | ### New in 0.1.3 (Released 2016/01/20) 15 | * Add Linux support 16 | * Select target from command line argument 17 | * Verbose Serilogs 18 | 19 | ### New in 0.1.2 (Released 2016/01/16) 20 | * Fixed SolutionInfo link 21 | * Changed Cake.CakeBoss alias to pass the target in as its own parameter 22 | 23 | ### New in 0.1.1 (Released 2016/01/07) 24 | * Add GitHub releases to build 25 | * Separate Test / Release cake scripts 26 | * Fix log formatting / default locations 27 | * Exclude TopShelf configuration result from logs 28 | * Add icon to agent 29 | 30 | ### New in 0.1.0 (Released 2016/01/05) 31 | * Scheduled Tasks 32 | 33 | ### New in 0.0.9 (Released 2015/12/30) 34 | * Working AppVeyor & visual studio debugging build process 35 | 36 | ### New in 0.0.8 (Released 2015/12/30) 37 | * Override ScriptRunner to alter the location of the addin directory 38 | 39 | ### New in 0.0.7 (Released 2015/12/24) 40 | * Improved host webservice 41 | 42 | ### New in 0.0.6 (Released 2015/12/10) 43 | * Update Cake references 44 | 45 | ### New in 0.0.5 (Released 2015/11/08) 46 | * Cake Addin for calling agent 47 | * Bootstrap using CompositeRoots for improved separation 48 | 49 | ### New in 0.0.4 (Released 2015/11/06) 50 | * Added Nancy webservice 51 | 52 | ### New in 0.0.3 (Released 2015/11/03) 53 | * Added Termination detection 54 | * Added Uptime check to detect StartUp 55 | 56 | ### New in 0.0.2 (Released 2015/10/12) 57 | * Fixed Rosyln experimental references 58 | 59 | ### New in 0.0.1 (Released 2015/10/10) 60 | * First release. -------------------------------------------------------------------------------- /src/CakeBoss.Host/packages.config: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | -------------------------------------------------------------------------------- /src/Cake.Host/Commands/HelpCommand.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using Cake.Core; 3 | using Cake.Core.Diagnostics; 4 | 5 | namespace Cake.Host.Commands 6 | { 7 | /// 8 | /// A command that displays help information. 9 | /// 10 | public sealed class HelpCommand : ICommand 11 | { 12 | private readonly IConsole _console; 13 | 14 | // Delegate factory used by Autofac. 15 | public delegate HelpCommand Factory(); 16 | 17 | public HelpCommand(IConsole console) 18 | { 19 | _console = console; 20 | } 21 | 22 | public bool Execute(CakeOptions options) 23 | { 24 | _console.WriteLine(); 25 | _console.WriteLine("Usage: Cake.Host.exe [build-script] [-verbosity=value]"); 26 | _console.WriteLine(" [-showdescription] [-dryrun] [..]"); 27 | _console.WriteLine(); 28 | _console.WriteLine("Example: Cake.Host.exe"); 29 | _console.WriteLine("Example: Cake.Host.exe build.Cake.Host -verbosity=quiet"); 30 | _console.WriteLine("Example: Cake.Host.exe build.Cake.Host -showdescription"); 31 | _console.WriteLine(); 32 | _console.WriteLine("Options:"); 33 | _console.WriteLine(" -verbosity=value Specifies the amount of information to be displayed."); 34 | _console.WriteLine(" ({0})", 35 | string.Join(", ", Enum.GetNames(typeof(Verbosity)))); 36 | _console.WriteLine(" -showdescription Shows description about tasks."); 37 | _console.WriteLine(" -dryrun Performs a dry run."); 38 | _console.WriteLine(" -version Displays version information."); 39 | _console.WriteLine(" -help Displays usage information."); 40 | _console.WriteLine(" -experimental Uses the nightly builds of Roslyn script engine."); 41 | _console.WriteLine(); 42 | 43 | return true; 44 | } 45 | } 46 | } -------------------------------------------------------------------------------- /src/Cake.Host/Scripting/Mono/CodeGen/Parsing/ScriptBuffer.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.IO; 3 | 4 | namespace Cake.Host.Scripting.Mono.CodeGen.Parsing 5 | { 6 | public sealed class ScriptBuffer : IDisposable 7 | { 8 | private readonly StringReader _reader; 9 | 10 | public int Position 11 | { 12 | get; private set; 13 | } 14 | 15 | public int PreviousToken 16 | { 17 | get; private set; 18 | } 19 | 20 | public int CurrentToken 21 | { 22 | get; private set; 23 | } 24 | 25 | public int NextToken 26 | { 27 | get; private set; 28 | } 29 | 30 | public bool ReachedEnd 31 | { 32 | get; private set; 33 | } 34 | 35 | public ScriptBuffer(string content) 36 | { 37 | _reader = new StringReader(content); 38 | 39 | // Set initial values. 40 | CurrentToken = ' '; 41 | Position = -1; 42 | } 43 | 44 | public void Dispose() 45 | { 46 | _reader.Dispose(); 47 | } 48 | 49 | public bool Read() 50 | { 51 | if (_reader.Peek() == -1) 52 | { 53 | ReachedEnd = true; 54 | return false; 55 | } 56 | 57 | PreviousToken = CurrentToken; 58 | CurrentToken = _reader.Read(); 59 | NextToken = _reader.Peek(); 60 | Position++; 61 | 62 | return true; 63 | } 64 | 65 | public int Peek() 66 | { 67 | return _reader.Peek(); 68 | } 69 | 70 | public void EatWhiteSpace() 71 | { 72 | while (true) 73 | { 74 | if (!Read()) 75 | { 76 | break; 77 | } 78 | var current = (char)CurrentToken; 79 | if (!char.IsWhiteSpace(current)) 80 | { 81 | break; 82 | } 83 | } 84 | } 85 | } 86 | } -------------------------------------------------------------------------------- /src/Cake.Host/Scripting/DescriptionScriptHost.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using Cake.Core; 5 | using Cake.Core.Scripting; 6 | 7 | namespace Cake.Host.Scripting 8 | { 9 | /// 10 | /// The script host used for showing task descriptions. 11 | /// 12 | public sealed class DescriptionScriptHost : ScriptHost 13 | { 14 | private readonly IConsole _console; 15 | private readonly Dictionary _descriptions; 16 | 17 | /// 18 | /// Initializes a new instance of the class. 19 | /// 20 | /// The engine. 21 | /// The context. 22 | /// The console. 23 | public DescriptionScriptHost(ICakeEngine engine, ICakeContext context, IConsole console) 24 | : base(engine, context) 25 | { 26 | if (console == null) 27 | { 28 | throw new ArgumentNullException("console"); 29 | } 30 | _console = console; 31 | _descriptions = new Dictionary(StringComparer.OrdinalIgnoreCase); 32 | } 33 | 34 | /// 35 | /// Runs the specified target. 36 | /// 37 | /// The target to run. 38 | /// The resulting report. 39 | public override CakeReport RunTarget(string target) 40 | { 41 | foreach (var task in Tasks) 42 | { 43 | _descriptions.Add(task.Name, task.Description); 44 | } 45 | 46 | _console.WriteLine(); 47 | _console.WriteLine("{0,-30}{1}", "Task", "Description"); 48 | _console.WriteLine(string.Concat(Enumerable.Range(0, 79).Select(s => "="))); 49 | foreach (var key in _descriptions.Keys) 50 | { 51 | _console.WriteLine("{0,-30}{1}", key, _descriptions[key]); 52 | } 53 | 54 | return null; 55 | } 56 | } 57 | } -------------------------------------------------------------------------------- /src/Cake.Host/CakeConsole.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using Cake.Core; 3 | 4 | namespace Cake.Host 5 | { 6 | public sealed class CakeConsole : IConsole 7 | { 8 | /// 9 | /// Gets or sets the foreground color. 10 | /// 11 | /// The foreground color. 12 | public ConsoleColor ForegroundColor 13 | { 14 | get { return Console.ForegroundColor; } 15 | set { Console.ForegroundColor = value; } 16 | } 17 | 18 | /// 19 | /// Gets or sets the background color. 20 | /// 21 | /// The background color. 22 | public ConsoleColor BackgroundColor 23 | { 24 | get { return Console.BackgroundColor; } 25 | set { Console.BackgroundColor = value; } 26 | } 27 | 28 | /// 29 | /// Writes the text representation of the specified array of objects to the 30 | /// console output using the specified format information. 31 | /// 32 | /// A composite format string 33 | /// An array of objects to write using format. 34 | public void Write(string format, params object[] arg) 35 | { 36 | Console.Write(format, arg); 37 | } 38 | 39 | /// 40 | /// Writes the text representation of the specified array of objects, followed 41 | /// by the current line terminator, to the console output using the specified 42 | /// format information. 43 | /// 44 | /// A composite format string 45 | /// An array of objects to write using format. 46 | public void WriteLine(string format, params object[] arg) 47 | { 48 | Console.WriteLine(format, arg); 49 | } 50 | 51 | /// 52 | /// Sets the foreground and background console colors to their defaults. 53 | /// 54 | public void ResetColor() 55 | { 56 | Console.ResetColor(); 57 | } 58 | } 59 | } -------------------------------------------------------------------------------- /src/CakeBoss.Host/Aliases/ScheduleAliases.cs: -------------------------------------------------------------------------------- 1 | #region Using Statements 2 | using Cake.Core; 3 | using Cake.Core.Annotations; 4 | using Cake.Core.Diagnostics; 5 | 6 | using FluentScheduler; 7 | using FluentScheduler.Model; 8 | #endregion 9 | 10 | 11 | 12 | namespace CakeBoss.Host 13 | { 14 | [CakeAliasCategory("CakeBoss")] 15 | [CakeNamespaceImport("FluentScheduler")] 16 | [CakeNamespaceImport("FluentScheduler.Model")] 17 | public static class ScheduleAliases 18 | { 19 | /// 20 | /// Starts the scheduled task manager 21 | /// 22 | /// The context. 23 | [CakeMethodAlias] 24 | [CakeAliasCategory("Schedule")] 25 | public static void StartSchedules(this ICakeContext context) 26 | { 27 | TaskRegistry instance = context.GetContainer().GetInstance(); 28 | TaskManager.Initialize(instance); 29 | 30 | context.Log.Information("Scheduled tasks started."); 31 | } 32 | 33 | /// 34 | /// Stops the scheduled task manager 35 | /// 36 | /// The context. 37 | [CakeMethodAlias] 38 | [CakeAliasCategory("Schedule")] 39 | public static void StopSchedules(this ICakeContext context) 40 | { 41 | TaskManager.Stop(); 42 | 43 | context.Log.Information("Scheduled tasks stopped."); 44 | } 45 | 46 | 47 | 48 | /// 49 | /// Adds a scheduled task to the task manager 50 | /// 51 | /// The context. 52 | /// The task you want to schedule. 53 | [CakeMethodAlias] 54 | [CakeAliasCategory("Schedule")] 55 | public static Schedule ScheduleTask(this ICakeContext context, string target) 56 | { 57 | context.Log.Information("Scheduling task '{0}'.", target); 58 | 59 | TaskRegistry instance = context.GetContainer().GetInstance(); 60 | return instance.Schedule(target); 61 | } 62 | } 63 | } 64 | 65 | -------------------------------------------------------------------------------- /src/Cake.Host/Arguments/ArgumentTokenizer.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.IO; 3 | using System.Text; 4 | 5 | namespace Cake.Host.Arguments 6 | { 7 | public static class ArgumentTokenizer 8 | { 9 | public static IEnumerable Tokenize(string arguments) 10 | { 11 | return Tokenize(new StringReader(arguments)); 12 | } 13 | 14 | private static IEnumerable Tokenize(StringReader reader) 15 | { 16 | while (reader.Peek() != -1) 17 | { 18 | var character = (char)reader.Peek(); 19 | switch (character) 20 | { 21 | case '\"': 22 | yield return ReadQuote(reader); 23 | break; 24 | case ' ': 25 | reader.Read(); 26 | break; 27 | default: 28 | yield return Read(reader); 29 | break; 30 | } 31 | } 32 | } 33 | 34 | private static string ReadQuote(StringReader reader) 35 | { 36 | var accumulator = new StringBuilder(); 37 | accumulator.Append((char)reader.Read()); 38 | while (reader.Peek() != -1) 39 | { 40 | var character = (char)reader.Peek(); 41 | if (character == '\"') 42 | { 43 | accumulator.Append((char)reader.Read()); 44 | break; 45 | } 46 | reader.Read(); 47 | accumulator.Append(character); 48 | } 49 | return accumulator.ToString(); 50 | } 51 | 52 | private static string Read(StringReader reader) 53 | { 54 | var accumulator = new StringBuilder(); 55 | accumulator.Append((char)reader.Read()); 56 | while (reader.Peek() != -1) 57 | { 58 | if ((char)reader.Peek() == ' ') 59 | { 60 | break; 61 | } 62 | accumulator.Append((char)reader.Read()); 63 | } 64 | return accumulator.ToString(); 65 | } 66 | } 67 | } -------------------------------------------------------------------------------- /src/Cake.Host/CakeArguments.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using Cake.Core; 4 | 5 | namespace Cake.Host 6 | { 7 | public sealed class CakeArguments : ICakeArguments 8 | { 9 | private readonly Dictionary _arguments; 10 | 11 | /// 12 | /// Gets the arguments. 13 | /// 14 | /// The arguments. 15 | public IReadOnlyDictionary Arguments 16 | { 17 | get { return _arguments; } 18 | } 19 | 20 | /// 21 | /// Initializes a new instance of the class. 22 | /// 23 | public CakeArguments() 24 | { 25 | _arguments = new Dictionary(StringComparer.OrdinalIgnoreCase); 26 | } 27 | 28 | /// 29 | /// Initializes the argument list. 30 | /// 31 | /// The arguments. 32 | public void SetArguments(IDictionary arguments) 33 | { 34 | if (arguments == null) 35 | { 36 | throw new ArgumentNullException("arguments"); 37 | } 38 | _arguments.Clear(); 39 | foreach (var argument in arguments) 40 | { 41 | _arguments.Add(argument.Key, argument.Value); 42 | } 43 | } 44 | 45 | /// 46 | /// Determines whether or not the specified argument exist. 47 | /// 48 | /// The argument name. 49 | /// 50 | /// true if the argument exist; otherwise false. 51 | /// 52 | public bool HasArgument(string name) 53 | { 54 | return _arguments.ContainsKey(name); 55 | } 56 | 57 | /// 58 | /// Gets an argument. 59 | /// 60 | /// The argument name. 61 | /// The argument value. 62 | public string GetArgument(string name) 63 | { 64 | return _arguments.ContainsKey(name) 65 | ? _arguments[name] : null; 66 | } 67 | } 68 | } -------------------------------------------------------------------------------- /script/Release.cake: -------------------------------------------------------------------------------- 1 | ////////////////////////////////////////////////////////////////////// 2 | // ARGUMENTS 3 | ////////////////////////////////////////////////////////////////////// 4 | 5 | var target = Argument("target", "Default"); 6 | var server = System.Environment.MachineName.ToLower(); 7 | 8 | 9 | 10 | 11 | 12 | ////////////////////////////////////////////////////////////////////// 13 | // SERVICE TASKS 14 | ////////////////////////////////////////////////////////////////////// 15 | 16 | Task("Start") 17 | .Description("Service Start.") 18 | .Does(() => 19 | { 20 | Information("---Add Scheduled Tasks---"); 21 | ScheduleTask("Deploy") 22 | .ToRunOnceIn(15).Seconds(); 23 | 24 | 25 | 26 | Information("---Configure the agent---"); 27 | ConfigureAgent(new AgentSettings() 28 | { 29 | Port = 8888, 30 | 31 | EnableTerminationCheck = false, 32 | EnableAPI = false, 33 | EnableScheduledTasks = true 34 | }); 35 | }); 36 | 37 | Task("Stop") 38 | .Description("Service Stop.") 39 | .Does(() => 40 | { 41 | 42 | }); 43 | 44 | Task("Startup") 45 | .Description("Server Startup.") 46 | .Does(() => 47 | { 48 | 49 | }); 50 | 51 | Task("Shutdown") 52 | .Description("Server Shutdown.") 53 | .Does(() => 54 | { 55 | 56 | }); 57 | 58 | Task("Terminate") 59 | .Description("AWS Instance Termination.") 60 | .Does(() => 61 | { 62 | 63 | }); 64 | 65 | 66 | 67 | 68 | 69 | ////////////////////////////////////////////////////////////////////// 70 | // DEPLOY TASKS 71 | ////////////////////////////////////////////////////////////////////// 72 | 73 | Task("Deploy") 74 | .Does(() => 75 | { 76 | Information("---Example Deployment---"); 77 | }); 78 | 79 | Task("Update") 80 | .Does(() => 81 | { 82 | Information("---Update Config---"); 83 | }); 84 | 85 | 86 | 87 | 88 | 89 | ////////////////////////////////////////////////////////////////////// 90 | // TASK TARGETS 91 | ////////////////////////////////////////////////////////////////////// 92 | 93 | Task("Default") 94 | .IsDependentOn("Start"); 95 | 96 | 97 | 98 | 99 | 100 | /////////////////////////////////////////////////////////////////////////////// 101 | // EXECUTION 102 | /////////////////////////////////////////////////////////////////////////////// 103 | 104 | RunTarget(target); -------------------------------------------------------------------------------- /src/Cake.CakeBoss/Settings/RemoteSettings.cs: -------------------------------------------------------------------------------- 1 | #region Using Statements 2 | using System; 3 | using System.Collections.Generic; 4 | 5 | using Cake.Core.IO; 6 | #endregion 7 | 8 | 9 | 10 | namespace Cake.CakeBoss 11 | { 12 | /// 13 | /// The settings used when running a remote target 14 | /// 15 | public class RemoteSettings 16 | { 17 | #region Fields (1) 18 | private string _Url; 19 | #endregion 20 | 21 | 22 | 23 | 24 | 25 | #region Constructor (1) 26 | /// 27 | /// Initializes a new instance of the class. 28 | /// 29 | public RemoteSettings() 30 | { 31 | this.Host = "localhost"; 32 | this.Port = 8080; 33 | 34 | _Url = ""; 35 | } 36 | #endregion 37 | 38 | 39 | 40 | 41 | 42 | #region Properties (5) 43 | /// 44 | /// Gets or sets the credentials to use when connecting 45 | /// 46 | public string Username { get; set; } 47 | 48 | /// 49 | /// Gets or sets the credentials to use when connecting 50 | /// 51 | public string Password { get; set; } 52 | 53 | 54 | 55 | /// 56 | /// Gets or sets the computer to connect to 57 | /// 58 | public string Host { get; set; } 59 | 60 | /// 61 | /// Gets or sets the remote port to connect on 62 | /// 63 | public int Port { get; set; } 64 | 65 | /// 66 | /// Gets or sets the full URI to connect to 67 | /// 68 | public string Url 69 | { 70 | set 71 | { 72 | _Url = value; 73 | } 74 | get 75 | { 76 | if (!String.IsNullOrEmpty(_Url)) 77 | { 78 | return _Url; 79 | } 80 | else 81 | { 82 | return "http://" + this.Host + ":" + this.Port.ToString(); 83 | } 84 | } 85 | } 86 | #endregion 87 | } 88 | } -------------------------------------------------------------------------------- /src/Cake.Host/CakeReportPrinter.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Globalization; 4 | using System.Linq; 5 | using Cake.Core; 6 | 7 | namespace Cake.Host 8 | { 9 | public sealed class CakeReportPrinter : ICakeReportPrinter 10 | { 11 | private readonly IConsole _console; 12 | 13 | public CakeReportPrinter(IConsole console) 14 | { 15 | _console = console; 16 | } 17 | 18 | public void Write(CakeReport report) 19 | { 20 | if (report == null) 21 | { 22 | throw new ArgumentNullException("report"); 23 | } 24 | 25 | try 26 | { 27 | var maxTaskNameLength = 29; 28 | foreach (var item in report) 29 | { 30 | if (item.TaskName.Length > maxTaskNameLength) 31 | { 32 | maxTaskNameLength = item.TaskName.Length; 33 | } 34 | } 35 | 36 | maxTaskNameLength++; 37 | string lineFormat = "{0,-" + maxTaskNameLength + "}{1,-20}"; 38 | _console.ForegroundColor = ConsoleColor.Green; 39 | 40 | // Write header. 41 | _console.WriteLine(); 42 | _console.WriteLine(lineFormat, "Task", "Duration"); 43 | _console.WriteLine(new string('-', 20 + maxTaskNameLength)); 44 | 45 | // Write task status. 46 | foreach (var item in report) 47 | { 48 | _console.WriteLine(lineFormat, item.TaskName, FormatTime(item.Duration)); 49 | } 50 | 51 | // Write footer. 52 | _console.WriteLine(new string('-', 20 + maxTaskNameLength)); 53 | _console.WriteLine(lineFormat, "Total:", FormatTime(GetTotalTime(report))); 54 | } 55 | finally 56 | { 57 | _console.ResetColor(); 58 | } 59 | } 60 | 61 | private static string FormatTime(TimeSpan time) 62 | { 63 | return time.ToString("c", CultureInfo.InvariantCulture); 64 | } 65 | 66 | private static TimeSpan GetTotalTime(IEnumerable entries) 67 | { 68 | return entries.Select(i => i.Duration) 69 | .Aggregate(TimeSpan.Zero, (t1, t2) => t1 + t2); 70 | } 71 | } 72 | } -------------------------------------------------------------------------------- /src/CakeBoss.Agent/packages.config: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | -------------------------------------------------------------------------------- /src/CakeBoss.Agent/Aliases/ApiAliases.cs: -------------------------------------------------------------------------------- 1 | #region Using Statements 2 | using System; 3 | 4 | using Cake.Core; 5 | using Cake.Core.Annotations; 6 | using Cake.Core.Diagnostics; 7 | 8 | using Nancy.Hosting.Self; 9 | 10 | using CakeBoss.Host; 11 | #endregion 12 | 13 | 14 | 15 | namespace CakeBoss.Agent 16 | { 17 | [CakeAliasCategory("CakeBoss")] 18 | public static class ApiAliases 19 | { 20 | /// 21 | /// Starts the agent api 22 | /// 23 | /// The context. 24 | [CakeMethodAlias] 25 | [CakeAliasCategory("Api")] 26 | public static void StartApi(this ICakeContext context) 27 | { 28 | if (Program.Host == null) 29 | { 30 | HostSettings hostSettings = context.GetContainer().GetInstance(); 31 | 32 | if (!String.IsNullOrEmpty(hostSettings.Url)) 33 | { 34 | Program.Host = new NancyHost(new Uri(hostSettings.Url), new ServiceBootstrapper(), new HostConfiguration() 35 | { 36 | EnableClientCertificates = true, 37 | 38 | UrlReservations = new UrlReservations() 39 | { 40 | CreateAutomatically = true 41 | } 42 | }); 43 | 44 | Program.Host.Start(); 45 | 46 | context.Log.Information("Starting agent api on url '{0}'.", hostSettings.Url); 47 | } 48 | else 49 | { 50 | context.Log.Error("Invalid host url."); 51 | } 52 | } 53 | else 54 | { 55 | context.Log.Error("Agent api has already been configured."); 56 | } 57 | } 58 | 59 | /// 60 | /// Stops the agent Api 61 | /// 62 | /// The context. 63 | [CakeMethodAlias] 64 | [CakeAliasCategory("Api")] 65 | public static void StopApi(this ICakeContext context) 66 | { 67 | if (Program.Host != null) 68 | { 69 | Program.Host.Stop(); 70 | Program.Host = null; 71 | 72 | context.Log.Information("Agent api stopped."); 73 | } 74 | else 75 | { 76 | context.Log.Error("Agent api is not running."); 77 | } 78 | } 79 | } 80 | } 81 | 82 | -------------------------------------------------------------------------------- /script/Test.cake: -------------------------------------------------------------------------------- 1 | #addin "Cake.Powershell" 2 | 3 | ////////////////////////////////////////////////////////////////////// 4 | // ARGUMENTS 5 | ////////////////////////////////////////////////////////////////////// 6 | 7 | var target = Argument("target", "Default"); 8 | 9 | 10 | 11 | 12 | 13 | /////////////////////////////////////////////////////////////////////////////// 14 | // SERVICE EVENTS 15 | /////////////////////////////////////////////////////////////////////////////// 16 | 17 | Task("Start") 18 | .Does(() => 19 | { 20 | Information("---Add Scheduled Tasks---"); 21 | ScheduleTask("Timed") 22 | .ToRunOnceIn(15).Seconds(); 23 | 24 | 25 | 26 | Information("---Start Agent---"); 27 | ConfigureAgent(new AgentSettings() 28 | { 29 | Port = 8888, 30 | 31 | EnableTerminationCheck = true, 32 | EnableAPI = true, 33 | EnableScheduledTasks = true 34 | }.AddUser("Admin", "Password1")); 35 | 36 | 37 | 38 | Information("---Call API---"); 39 | RunRemoteTarget("Remote", new RemoteSettings() 40 | { 41 | Username = "Admin", 42 | Password = "Password1", 43 | Port = 8888 44 | }); 45 | }); 46 | 47 | Task("Stop") 48 | .Does(() => 49 | { 50 | Information("---Stop---"); 51 | }); 52 | 53 | Task("Update") 54 | .Does(() => 55 | { 56 | Information("---Update Config---"); 57 | }); 58 | 59 | 60 | 61 | 62 | 63 | /////////////////////////////////////////////////////////////////////////////// 64 | // SPECIAL EVENTS 65 | /////////////////////////////////////////////////////////////////////////////// 66 | 67 | Task("Remote") 68 | .Does(() => 69 | { 70 | Information("---Remote Webservice Call---"); 71 | StartPowershellScript("Write-Host", args => 72 | { 73 | args.AppendQuoted("Triggering remote deployment"); 74 | }); 75 | }); 76 | 77 | Task("Timed") 78 | .Does(() => 79 | { 80 | Information("---Timed Task Call---"); 81 | UpdateConfig("../../../../script/Release.cake"); 82 | }); 83 | 84 | 85 | 86 | 87 | ////////////////////////////////////////////////////////////////////// 88 | // TASK TARGETS 89 | ////////////////////////////////////////////////////////////////////// 90 | 91 | Task("Default") 92 | .IsDependentOn("Start"); 93 | 94 | 95 | 96 | 97 | 98 | /////////////////////////////////////////////////////////////////////////////// 99 | // EXECUTION 100 | /////////////////////////////////////////////////////////////////////////////// 101 | 102 | RunTarget(target); -------------------------------------------------------------------------------- /src/Cake.Host/Scripting/Mono/MonoConsoleReportPrinter.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Globalization; 3 | using Cake.Core.Diagnostics; 4 | using Cake.Core.IO; 5 | using Mono.CSharp; 6 | 7 | namespace Cake.Host.Scripting.Mono 8 | { 9 | public sealed class MonoConsoleReportPrinter : ReportPrinter 10 | { 11 | private readonly ICakeLog _log; 12 | 13 | public MonoConsoleReportPrinter(ICakeLog log) 14 | { 15 | _log = log; 16 | } 17 | 18 | public override void Print(AbstractMessage msg, bool showFullPath) 19 | { 20 | if (msg == null) 21 | { 22 | return; 23 | } 24 | 25 | var message = GetFormattedLogMessage(msg); 26 | 27 | if (msg.IsWarning) 28 | { 29 | _log.Warning(message); 30 | } 31 | else if (IsError(msg)) 32 | { 33 | _log.Error(message); 34 | } 35 | else 36 | { 37 | _log.Verbose(message); 38 | } 39 | } 40 | 41 | private static string GetFormattedLogMessage(AbstractMessage message) 42 | { 43 | var path = GetSourcePath(message); 44 | var row = message.Location.Row; 45 | var column = message.Location.Column; 46 | 47 | return string.Format( 48 | CultureInfo.InvariantCulture, 49 | "{0} ({1},{2}): {3}", 50 | path.FullPath, row, column, message.Text); 51 | } 52 | 53 | private static FilePath GetSourcePath(AbstractMessage message) 54 | { 55 | string filename = null; 56 | 57 | try 58 | { 59 | if (message.Location.SourceFile != null && message.Location.SourceFile.Name != null) 60 | { 61 | filename = message.Location.SourceFile.Name; 62 | } 63 | } 64 | catch 65 | { 66 | // Fix for issue #298 (https://github.com/Cake.Host-build/Cake.Host/issues/298) 67 | // Not pretty but it should take care of the exception being thrown 68 | // in certain situations when accessing the SourceFile property. 69 | } 70 | 71 | return new FilePath(filename ?? "unknown.Cake.Host").GetFilename(); 72 | } 73 | 74 | private static bool IsError(AbstractMessage message) 75 | { 76 | return message.MessageType != null && 77 | message.MessageType.Equals("error", StringComparison.OrdinalIgnoreCase); 78 | } 79 | } 80 | } -------------------------------------------------------------------------------- /src/Cake.Host/Scripting/Roslyn/Stable/RoslynScriptSession.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Reflection; 4 | using Cake.Core.Diagnostics; 5 | using Cake.Core.IO; 6 | using Cake.Core.Scripting; 7 | 8 | namespace Cake.Host.Scripting.Roslyn.Stable 9 | { 10 | public sealed class RoslynScriptSession : IScriptSession 11 | { 12 | private readonly global::Roslyn.Scripting.Session _roslynSession; 13 | private readonly ICakeLog _log; 14 | private readonly HashSet _importedNamespaces; 15 | 16 | public RoslynScriptSession(IScriptHost host, ICakeLog log) 17 | { 18 | if (host == null) 19 | { 20 | throw new ArgumentNullException("host"); 21 | } 22 | if (log == null) 23 | { 24 | throw new ArgumentNullException("log"); 25 | } 26 | 27 | var roslynScriptEngine = new global::Roslyn.Scripting.CSharp.ScriptEngine(); 28 | _roslynSession = roslynScriptEngine.CreateSession(host, typeof(IScriptHost)); 29 | 30 | _log = log; 31 | _importedNamespaces = new HashSet(); 32 | } 33 | 34 | public void AddReference(FilePath path) 35 | { 36 | if (path == null) 37 | { 38 | throw new ArgumentNullException("path"); 39 | } 40 | _log.Debug("Adding reference to {0}...", path.GetFilename().FullPath); 41 | _roslynSession.AddReference(path.FullPath); 42 | } 43 | 44 | public void AddReference(Assembly assembly) 45 | { 46 | if (assembly == null) 47 | { 48 | throw new ArgumentNullException("assembly"); 49 | } 50 | _log.Debug("Adding reference to {0}...", new FilePath(assembly.Location).GetFilename().FullPath); 51 | _roslynSession.AddReference(assembly); 52 | } 53 | 54 | public void ImportNamespace(string @namespace) 55 | { 56 | if (!_importedNamespaces.Contains(@namespace)) 57 | { 58 | _log.Debug("Importing namespace {0}...", @namespace); 59 | _roslynSession.ImportNamespace(@namespace); 60 | _importedNamespaces.Add(@namespace); 61 | } 62 | } 63 | 64 | public void Execute(Script script) 65 | { 66 | // Generate the script code. 67 | var generator = new RoslynCodeGenerator(); 68 | var code = generator.Generate(script); 69 | 70 | _log.Verbose("Compiling build script..."); 71 | _roslynSession.Execute(code); 72 | } 73 | } 74 | } -------------------------------------------------------------------------------- /src/Cake.Host/CakeOptions.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using Cake.Core.Diagnostics; 4 | using Cake.Core.IO; 5 | 6 | namespace Cake.Host 7 | { 8 | /// 9 | /// The options that determines how the application should behave. 10 | /// 11 | public sealed class CakeOptions 12 | { 13 | private readonly Dictionary _arguments; 14 | 15 | /// 16 | /// Gets or sets the output verbosity. 17 | /// 18 | /// The output verbosity. 19 | public Verbosity Verbosity { get; set; } 20 | 21 | /// 22 | /// Gets or sets the build script. 23 | /// 24 | /// The build script. 25 | public FilePath Script { get; set; } 26 | 27 | /// 28 | /// Gets the script arguments. 29 | /// 30 | /// The script arguments. 31 | public IDictionary Arguments 32 | { 33 | get { return _arguments; } 34 | } 35 | 36 | /// 37 | /// Gets or sets a value indicating whether to show task descriptions. 38 | /// 39 | /// 40 | /// true to show task description; otherwise, false. 41 | /// 42 | public bool ShowDescription { get; set; } 43 | 44 | /// 45 | /// Gets or sets a value indicating whether to perform a dry run. 46 | /// 47 | /// 48 | /// true if a dry run should be performed; otherwise, false. 49 | /// 50 | public bool PerformDryRun { get; set; } 51 | 52 | /// 53 | /// Gets or sets a value indicating whether to show help. 54 | /// 55 | /// 56 | /// true to show help; otherwise, false. 57 | /// 58 | public bool ShowHelp { get; set; } 59 | 60 | /// 61 | /// Gets or sets a value indicating whether to show version information. 62 | /// 63 | /// 64 | /// true to show version information; otherwise, false. 65 | /// 66 | public bool ShowVersion { get; set; } 67 | 68 | /// 69 | /// Initializes a new instance of the class. 70 | /// 71 | public CakeOptions() 72 | { 73 | _arguments = new Dictionary(StringComparer.OrdinalIgnoreCase); 74 | 75 | Verbosity = Verbosity.Normal; 76 | ShowDescription = false; 77 | ShowHelp = false; 78 | } 79 | } 80 | } -------------------------------------------------------------------------------- /src/CakeBoss.Agent.Tests/packages.config: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | -------------------------------------------------------------------------------- /src/Cake.Host/Scripting/Roslyn/Nightly/RoslynNightlyScriptSession.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Reflection; 5 | using Cake.Core.Diagnostics; 6 | using Cake.Core.IO; 7 | using Cake.Core.Scripting; 8 | 9 | namespace Cake.Host.Scripting.Roslyn.Nightly 10 | { 11 | public sealed class RoslynNightlyScriptSession : IScriptSession 12 | { 13 | private readonly IScriptHost _host; 14 | private readonly ICakeLog _log; 15 | private readonly HashSet _referencePaths; 16 | private readonly HashSet _references; 17 | private readonly HashSet _namespaces; 18 | 19 | public RoslynNightlyScriptSession(IScriptHost host, ICakeLog log) 20 | { 21 | _host = host; 22 | _log = log; 23 | 24 | _referencePaths = new HashSet(PathComparer.Default); 25 | _references = new HashSet(); 26 | _namespaces = new HashSet(StringComparer.Ordinal); 27 | } 28 | 29 | public void AddReference(FilePath path) 30 | { 31 | if (path == null) 32 | { 33 | throw new ArgumentNullException("path"); 34 | } 35 | _log.Debug("Adding reference to {0}...", path.GetFilename().FullPath); 36 | _referencePaths.Add(path); 37 | } 38 | 39 | public void AddReference(Assembly assembly) 40 | { 41 | if (assembly == null) 42 | { 43 | throw new ArgumentNullException("assembly"); 44 | } 45 | _log.Debug("Adding reference to {0}...", new FilePath(assembly.Location).GetFilename().FullPath); 46 | _references.Add(assembly); 47 | } 48 | 49 | public void ImportNamespace(string @namespace) 50 | { 51 | if (!_namespaces.Contains(@namespace)) 52 | { 53 | _log.Debug("Importing namespace {0}...", @namespace); 54 | _namespaces.Add(@namespace); 55 | } 56 | } 57 | 58 | public void Execute(Script script) 59 | { 60 | // Generate the script code. 61 | var generator = new RoslynCodeGenerator(); 62 | var code = generator.Generate(script); 63 | 64 | // Create the script options dynamically. 65 | var options = Microsoft.CodeAnalysis.Scripting.ScriptOptions.Default 66 | .AddNamespaces(_namespaces) 67 | .AddReferences(_references) 68 | .AddReferences(_referencePaths.Select(r => r.FullPath)); 69 | 70 | _log.Verbose("Compiling build script..."); 71 | Microsoft.CodeAnalysis.Scripting.CSharp.CSharpScript.Eval(code, options, _host); 72 | } 73 | } 74 | } -------------------------------------------------------------------------------- /src/CakeBoss.Agent/Service/TerminationService.cs: -------------------------------------------------------------------------------- 1 | #region Using Statements 2 | using System; 3 | using System.Timers; 4 | using System.Net; 5 | #endregion 6 | 7 | 8 | 9 | namespace CakeBoss.Agent 10 | { 11 | public class TerminationService : ITerminationService 12 | { 13 | #region Fields (3) 14 | private IAgentService _Agent; 15 | 16 | private Timer _Timer; 17 | private object _Lock; 18 | #endregion 19 | 20 | 21 | 22 | 23 | 24 | #region Constructor (1) 25 | public TerminationService(IAgentService agent) 26 | { 27 | if (agent == null) 28 | { 29 | throw new ArgumentNullException("agent"); 30 | } 31 | 32 | _Agent = agent; 33 | 34 | _Timer = new Timer(5000); 35 | _Timer.Elapsed += this.Tick; 36 | 37 | _Lock = new Object(); 38 | } 39 | #endregion 40 | 41 | 42 | 43 | 44 | 45 | #region Properties (2) 46 | public bool Enabled 47 | { 48 | get 49 | { 50 | return _Timer.Enabled; 51 | } 52 | set 53 | { 54 | _Timer.Enabled = value; 55 | } 56 | } 57 | 58 | public int Interval 59 | { 60 | get 61 | { 62 | return Convert.ToInt32(_Timer.Interval); 63 | } 64 | set 65 | { 66 | _Timer.Interval = value; 67 | } 68 | } 69 | #endregion 70 | 71 | 72 | 73 | 74 | 75 | #region Functions (2) 76 | public void Tick(object sender, EventArgs args) 77 | { 78 | lock (_Lock) 79 | { 80 | if (!_Timer.Enabled) 81 | { 82 | return; 83 | } 84 | 85 | if (this.Termination()) 86 | { 87 | _Timer.Stop(); 88 | _Agent.Terminate(); 89 | } 90 | } 91 | } 92 | 93 | public bool Termination() 94 | { 95 | try 96 | { 97 | string value = new WebClient().DownloadString(new Uri("http://169.254.169.254/latest/meta-data/spot/termination-time")); 98 | return !String.IsNullOrEmpty(value); 99 | } 100 | catch 101 | { 102 | return false; 103 | } 104 | } 105 | #endregion 106 | } 107 | } 108 | -------------------------------------------------------------------------------- /src/Cake.Host/Commands/VersionCommand.cs: -------------------------------------------------------------------------------- 1 | using System.Diagnostics; 2 | using Cake.Core; 3 | 4 | namespace Cake.Host.Commands 5 | { 6 | /// 7 | /// A command that shows version information. 8 | /// 9 | public sealed class VersionCommand : ICommand 10 | { 11 | private readonly IConsole _console; 12 | 13 | // Delegate factory used by Autofac. 14 | public delegate VersionCommand Factory(); 15 | 16 | public VersionCommand(IConsole console) 17 | { 18 | _console = console; 19 | } 20 | 21 | public bool Execute(CakeOptions options) 22 | { 23 | _console.WriteLine(); 24 | _console.WriteLine(@" +## #;;'"); 25 | _console.WriteLine(@" #;;# .+;;;;+,"); 26 | _console.WriteLine(@" '+;;#;,+';;;;;'#."); 27 | _console.WriteLine(@" ++'''';;;;;;;;;;# ;#;"); 28 | _console.WriteLine(@" ##';;;;++'+#;;;;;'. `#:"); 29 | _console.WriteLine(@" ;# '+'';;;;;;;;;'#` #."); 30 | _console.WriteLine(@" `#, .'++;;;;;':..........#"); 31 | _console.WriteLine(@" '+ `.........';;;;':.........#"); 32 | _console.WriteLine(@" #..................+;;;;;':........#"); 33 | _console.WriteLine(@" #..................#';;;;;'+''''''.#"); 34 | _console.WriteLine(@" #.......,:;''''''''##';;;;;'+'''''#,"); 35 | _console.WriteLine(@" #''''''''''''''''''###';;;;;;+''''#"); 36 | _console.WriteLine(@" #''''''''''''''''''####';;;;;;#'''#"); 37 | _console.WriteLine(@" #''''''''''''''''''#####';;;;;;#''#"); 38 | _console.WriteLine(@" #''''''''''''''''''######';;;;;;#'#"); 39 | _console.WriteLine(@" #''''''''''''''''''#######';;;;;;##"); 40 | _console.WriteLine(@" #''''''''''''''''''########';;;;;;#"); 41 | _console.WriteLine(@" #''''''''''''++####+;#######';;;;;;#"); 42 | _console.WriteLine(@" #+####':,` ,#####';;;;;;'"); 43 | _console.WriteLine(@" +##'''''+."); 44 | _console.WriteLine(@" ___ _ ___ _ _ _ "); 45 | _console.WriteLine(@" / __\__ _| | _____ / __\_ _(_) | __| |"); 46 | _console.WriteLine(@" / / / _` | |/ / _ \/__\// | | | | |/ _` |"); 47 | _console.WriteLine(@"/ /___ (_| | < __/ \/ \ |_| | | | (_| |"); 48 | _console.WriteLine(@"\____/\__,_|_|\_\___\_____/\__,_|_|_|\__,_|"); 49 | _console.WriteLine(); 50 | _console.WriteLine(@" Version {0}", GetVersion()); 51 | _console.WriteLine(); 52 | 53 | return true; 54 | } 55 | 56 | private static string GetVersion() 57 | { 58 | var assembly = typeof(CakeApplication).Assembly; 59 | return FileVersionInfo.GetVersionInfo(assembly.Location).ProductVersion; 60 | } 61 | } 62 | } -------------------------------------------------------------------------------- /src/CakeBoss.Host/Host/ScriptConventions.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Reflection; 5 | using Cake.Core.IO; 6 | using Cake.Core.Scripting; 7 | 8 | namespace CakeBoss.Host 9 | { 10 | /// 11 | /// The script conventions used by Cake. 12 | /// 13 | public sealed class ScriptConventions : IScriptConventions 14 | { 15 | private readonly IFileSystem _fileSystem; 16 | 17 | /// 18 | /// Initializes a new instance of the class. 19 | /// 20 | /// The file system. 21 | public ScriptConventions(IFileSystem fileSystem) 22 | { 23 | _fileSystem = fileSystem; 24 | } 25 | 26 | /// 27 | /// Gets the default namespaces. 28 | /// 29 | /// A list containing all default namespaces. 30 | public IReadOnlyList GetDefaultNamespaces() 31 | { 32 | return new List 33 | { 34 | "System", "System.Collections.Generic", "System.Linq", 35 | "System.Text", "System.Threading.Tasks", "System.IO", 36 | "Cake.Core", "Cake.Core.IO", "Cake.Core.Scripting", "Cake.Core.Diagnostics", 37 | "CakeBoss.Host", "CakeBoss.Agent", "Cake.CakeBoss", 38 | "FluentScheduler.Model" 39 | }; 40 | } 41 | 42 | /// 43 | /// Gets the default assemblies. 44 | /// 45 | /// The root to where to find Cake related assemblies. 46 | /// A list containing all default assemblies. 47 | public IReadOnlyList GetDefaultAssemblies(DirectoryPath root) 48 | { 49 | // Prepare the default assemblies. 50 | var defaultAssemblies = new List 51 | { 52 | typeof(Action).Assembly, // mscorlib 53 | typeof(Uri).Assembly, // System 54 | typeof(IQueryable).Assembly, // System.Core 55 | typeof(System.Data.DataTable).Assembly, // System.Data 56 | typeof(System.Xml.XmlReader).Assembly, // System.Xml 57 | typeof(System.Xml.Linq.XDocument).Assembly, // System.Xml.Linq 58 | }; 59 | 60 | // Load other Cake-related assemblies that we need. 61 | var assemblyDirectory = _fileSystem.GetDirectory(root); 62 | var patterns = new[] { "Cake.Core.dll", "Cake.Common.dll", "CakeBoss.Host.dll", "CakeBoss.Agent.exe", "Cake.CakeBoss.dll", "FluentScheduler.dll" }; 63 | foreach (var pattern in patterns) 64 | { 65 | var cakeAssemblies = assemblyDirectory.GetFiles(pattern, SearchScope.Current); 66 | foreach (var cakeAssembly in cakeAssemblies) 67 | { 68 | var assembly = Assembly.LoadFrom(cakeAssembly.Path.FullPath); 69 | defaultAssemblies.Add(assembly); 70 | } 71 | } 72 | 73 | // Return the assemblies. 74 | return defaultAssemblies; 75 | } 76 | } 77 | } 78 | -------------------------------------------------------------------------------- /src/CakeBoss.Agent/Aliases/AgentAliases.cs: -------------------------------------------------------------------------------- 1 | #region Using Statements 2 | using System; 3 | 4 | using Cake.Core; 5 | using Cake.Core.IO; 6 | using Cake.Core.Annotations; 7 | using Cake.Core.Diagnostics; 8 | using Cake.Common.IO; 9 | 10 | using LightInject; 11 | using Nancy.Hosting.Self; 12 | 13 | using CakeBoss.Host; 14 | #endregion 15 | 16 | 17 | 18 | namespace CakeBoss.Agent 19 | { 20 | [CakeAliasCategory("CakeBoss")] 21 | public static class AgentAliases 22 | { 23 | /// 24 | /// Configures the agent using the specified information. 25 | /// 26 | /// The context. 27 | /// The agent settings. 28 | [CakeMethodAlias] 29 | [CakeAliasCategory("Agent")] 30 | public static void ConfigureAgent(this ICakeContext context, AgentSettings settings) 31 | { 32 | if (settings == null) 33 | { 34 | throw new ArgumentNullException("settings"); 35 | } 36 | 37 | 38 | 39 | //Configure 40 | context.ConfigureHost(settings); 41 | 42 | 43 | 44 | //Start 45 | if (settings.EnableTerminationCheck) 46 | { 47 | context.StartTerminationCheck(); 48 | } 49 | 50 | if (settings.EnableAPI) 51 | { 52 | context.StartApi(); 53 | } 54 | 55 | if (settings.EnableScheduledTasks) 56 | { 57 | context.StartSchedules(); 58 | } 59 | } 60 | 61 | 62 | 63 | /// 64 | /// reloads the agent from the existing config file 65 | /// 66 | /// The context. 67 | /// The path to the new config file. 68 | [CakeMethodAlias] 69 | [CakeAliasCategory("Agent")] 70 | public static void ReconfigureAgent(this ICakeContext context, FilePath path) 71 | { 72 | // Update config file 73 | context.CopyFile(path, FilePath.FromString("./CakeBoss.Agent.cake")); 74 | context.Log.Information("Config file updated."); 75 | 76 | context.RestartAgent(); 77 | } 78 | 79 | /// r 80 | /// Reloads the agent from the existing config file 81 | /// 82 | /// The context. 83 | [CakeMethodAlias] 84 | [CakeAliasCategory("Agent")] 85 | public static void RestartAgent(this ICakeContext context) 86 | { 87 | // Stop services 88 | context.StartTerminationCheck(); 89 | context.StopSchedules(); 90 | context.StopApi(); 91 | 92 | // Clear all register references 93 | Program.Container = Program.CreateContainer(); 94 | 95 | // Restart the agent 96 | IAgentService service = context.GetContainer().GetInstance(); 97 | service.RunTarget("Start", true); 98 | context.Log.Information("Cake engine reloaded."); 99 | } 100 | } 101 | } 102 | -------------------------------------------------------------------------------- /src/Cake.Host/Diagnostics/CakeBuildLog.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using Cake.Core; 4 | using Cake.Core.Diagnostics; 5 | using Cake.Host.Diagnostics.Formatting; 6 | 7 | namespace Cake.Host.Diagnostics 8 | { 9 | public sealed class CakeBuildLog : IVerbosityAwareLog 10 | { 11 | private readonly IConsole _console; 12 | private readonly object _lock; 13 | private readonly IDictionary _palettes; 14 | 15 | public Verbosity Verbosity { get; private set; } 16 | 17 | public CakeBuildLog(IConsole console, Verbosity verbosity = Verbosity.Normal) 18 | { 19 | _console = console; 20 | _lock = new object(); 21 | _palettes = CreatePalette(); 22 | Verbosity = verbosity; 23 | } 24 | 25 | public void Write(Verbosity verbosity, LogLevel level, string format, params object[] args) 26 | { 27 | if (verbosity > Verbosity) 28 | { 29 | return; 30 | } 31 | lock (_lock) 32 | { 33 | try 34 | { 35 | var palette = _palettes[level]; 36 | var tokens = FormatParser.Parse(format); 37 | foreach (var token in tokens) 38 | { 39 | SetPalette(token, palette); 40 | _console.Write("{0}", token.Render(args)); 41 | } 42 | } 43 | finally 44 | { 45 | _console.ResetColor(); 46 | _console.WriteLine(); 47 | } 48 | } 49 | } 50 | 51 | public void SetVerbosity(Verbosity verbosity) 52 | { 53 | Verbosity = verbosity; 54 | } 55 | 56 | private void SetPalette(FormatToken token, ConsolePalette palette) 57 | { 58 | var property = token as PropertyToken; 59 | if (property != null) 60 | { 61 | _console.BackgroundColor = palette.ArgumentBackground; 62 | _console.ForegroundColor = palette.ArgumentForeground; 63 | } 64 | else 65 | { 66 | _console.BackgroundColor = palette.Background; 67 | _console.ForegroundColor = palette.Foreground; 68 | } 69 | } 70 | 71 | private IDictionary CreatePalette() 72 | { 73 | var background = _console.BackgroundColor; 74 | var palette = new Dictionary 75 | { 76 | { LogLevel.Error, new ConsolePalette(ConsoleColor.DarkRed, ConsoleColor.White, ConsoleColor.Red, ConsoleColor.White) }, 77 | { LogLevel.Warning, new ConsolePalette(background, ConsoleColor.Yellow, background, ConsoleColor.Yellow) }, 78 | { LogLevel.Information, new ConsolePalette(background, ConsoleColor.White, ConsoleColor.DarkBlue, ConsoleColor.White) }, 79 | { LogLevel.Verbose, new ConsolePalette(background, ConsoleColor.Gray, background, ConsoleColor.White) }, 80 | { LogLevel.Debug, new ConsolePalette(background, ConsoleColor.DarkGray, background, ConsoleColor.Gray) } 81 | }; 82 | return palette; 83 | } 84 | } 85 | } -------------------------------------------------------------------------------- /src/Cake.CakeBoss/Cake.CakeBoss.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Debug 6 | AnyCPU 7 | {8C311438-E0F0-4A47-AC31-DA29BF901FB2} 8 | Library 9 | Properties 10 | Cake.CakeBoss 11 | Cake.CakeBoss 12 | v4.5 13 | 512 14 | 15 | 16 | 17 | true 18 | full 19 | false 20 | bin\Debug\ 21 | DEBUG;TRACE 22 | prompt 23 | 4 24 | bin\Debug\Cake.CakeBoss.xml 25 | 26 | 27 | pdbonly 28 | true 29 | bin\Release\ 30 | TRACE 31 | prompt 32 | 4 33 | bin\Release\Cake.CakeBoss.xml 34 | 35 | 36 | 37 | ..\packages\Cake.Core.0.6.4\lib\net45\Cake.Core.dll 38 | True 39 | 40 | 41 | ..\packages\RestSharp.105.2.3\lib\net45\RestSharp.dll 42 | True 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | Properties\SolutionInfo.cs 57 | 58 | 59 | 60 | 61 | 62 | 63 | 70 | -------------------------------------------------------------------------------- /src/Cake.Host/Scripting/Mono/CodeGen/MonoCodeGenerator.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.Text; 3 | using Cake.Core.Scripting; 4 | using Cake.Core.Scripting.CodeGen; 5 | using Cake.Host.Scripting.Mono.CodeGen.Parsing; 6 | 7 | namespace Cake.Host.Scripting.Mono.CodeGen 8 | { 9 | public sealed class MonoCodeGenerator 10 | { 11 | public static string Generate(Script script) 12 | { 13 | // Process the script. 14 | IReadOnlyList blocks; 15 | script = MonoScriptProcessor.Process(script, out blocks); 16 | 17 | var code = new StringBuilder(); 18 | 19 | if (script.UsingAliasDirectives.Count > 0) 20 | { 21 | foreach (var usingAliasDirective in script.UsingAliasDirectives) 22 | { 23 | code.AppendLine(usingAliasDirective); 24 | } 25 | code.AppendLine(); 26 | } 27 | 28 | code.AppendLine("public class CakeBuildScriptImpl"); 29 | code.AppendLine("{"); 30 | code.AppendLine(" public CakeBuildScriptImpl (IScriptHost scriptHost)"); 31 | code.AppendLine(" {"); 32 | code.AppendLine(" ScriptHost = scriptHost;"); 33 | code.AppendLine(" }"); 34 | code.AppendLine(); 35 | code.AppendLine(GetAliasCode(script)); 36 | code.AppendLine(); 37 | code.AppendLine(GetScriptHostProxy()); 38 | code.AppendLine(); 39 | 40 | foreach (var block in blocks) 41 | { 42 | code.AppendLine(block.Content); 43 | code.AppendLine(); 44 | } 45 | 46 | code.AppendLine(" public void Execute ()"); 47 | code.AppendLine(" {"); 48 | 49 | code.AppendLine(string.Join("\n", script.Lines)); 50 | code.AppendLine(); 51 | code.AppendLine(" }"); 52 | code.AppendLine("}"); 53 | 54 | return code.ToString(); 55 | } 56 | 57 | private static string GetAliasCode(Script context) 58 | { 59 | var result = new List(); 60 | foreach (var alias in context.Aliases) 61 | { 62 | result.Add(alias.Type == ScriptAliasType.Method 63 | ? MethodAliasGenerator.Generate(alias.Method) 64 | : PropertyAliasGenerator.Generate(alias.Method)); 65 | } 66 | return string.Join("\r\n", result); 67 | } 68 | 69 | private static string GetScriptHostProxy() 70 | { 71 | // TODO: Generate this from interface. 72 | var rules = new[] 73 | { 74 | "IScriptHost ScriptHost { get; set; }", 75 | "ICakeContext Context { get { return ScriptHost.Context; } }", 76 | "IReadOnlyList Tasks { get { return ScriptHost.Tasks; } }", 77 | "CakeTaskBuilder Task(string name) { return ScriptHost.Task (name); }", 78 | "void Setup (Action action) { ScriptHost.Setup (action); }", 79 | "void Teardown(Action action) { ScriptHost.Teardown (action); }", 80 | "CakeReport RunTarget(string target) { return ScriptHost.RunTarget (target); }" 81 | }; 82 | 83 | return " " + string.Join("\r\n ", rules); 84 | } 85 | } 86 | } -------------------------------------------------------------------------------- /src/Cake.CakeBoss/Aliases/AgentAliases.cs: -------------------------------------------------------------------------------- 1 | #region Using Statements 2 | using System; 3 | using System.Net; 4 | 5 | using Cake.Core; 6 | using Cake.Core.Annotations; 7 | using Cake.Core.Diagnostics; 8 | 9 | using RestSharp; 10 | using RestSharp.Authenticators; 11 | #endregion 12 | 13 | 14 | 15 | namespace Cake.CakeBoss 16 | { 17 | /// 18 | /// Contains Cake aliases for calling CakeBoss agents 19 | /// 20 | [CakeAliasCategory("CakeBoss")] 21 | public static class AgentAliases 22 | { 23 | /// 24 | /// Run a target on a remote CakeBoss agent 25 | /// 26 | /// The cake context. 27 | /// The script target to run. 28 | /// The information about the remote target to run. 29 | /// If the target ran successfully 30 | [CakeMethodAlias] 31 | public static bool RunRemoteTarget(this ICakeContext context, string target, RemoteSettings settings) 32 | { 33 | if (String.IsNullOrEmpty(target)) 34 | { 35 | throw new ArgumentNullException("target"); 36 | } 37 | 38 | if (settings == null) 39 | { 40 | throw new ArgumentNullException("settings"); 41 | } 42 | 43 | if (String.IsNullOrEmpty(settings.Username)) 44 | { 45 | throw new ArgumentNullException("settings.Username"); 46 | } 47 | if (String.IsNullOrEmpty(settings.Password)) 48 | { 49 | throw new ArgumentNullException("settings.Password"); 50 | } 51 | 52 | if (String.IsNullOrEmpty(settings.Url)) 53 | { 54 | throw new ArgumentNullException("settings.Url"); 55 | } 56 | 57 | 58 | 59 | //Client 60 | string url = settings.Url; 61 | 62 | if (!url.EndsWith("/agent")) 63 | { 64 | if (!url.EndsWith("/")) 65 | { 66 | url += "/"; 67 | } 68 | 69 | url += "agent"; 70 | } 71 | 72 | RestClient client = new RestClient(url); 73 | client.Authenticator = new HttpBasicAuthenticator(settings.Username, settings.Password); 74 | 75 | 76 | 77 | //Request 78 | RestRequest request = new RestRequest("/run/" + target, Method.POST); 79 | IRestResponse response = client.Execute(request); 80 | 81 | if (response.StatusCode == HttpStatusCode.OK) 82 | { 83 | context.Log.Information("Target {0} ran on agent {1}.", target, url); 84 | return true; 85 | } 86 | else if (response.StatusCode == HttpStatusCode.Unauthorized) 87 | { 88 | context.Log.Error("Unable to authorise. Check the username / password."); 89 | } 90 | else if (response.ErrorMessage == "Unable to connect to the remote server") 91 | { 92 | context.Log.Error("Unable to connect. Check the url for the remote host {1}.", target, url); 93 | } 94 | else 95 | { 96 | context.Log.Error(response.ErrorMessage); 97 | } 98 | 99 | return false; 100 | } 101 | } 102 | } 103 | -------------------------------------------------------------------------------- /src/CakeBoss.Agent/Service/AgentService.cs: -------------------------------------------------------------------------------- 1 | #region Using Statements 2 | using System; 3 | using System.Collections.Generic; 4 | 5 | using Cake.Core; 6 | using Cake.Host.Scripting; 7 | 8 | using CakeBoss.Host; 9 | #endregion 10 | 11 | 12 | 13 | namespace CakeBoss.Agent 14 | { 15 | public class AgentService : IAgentService 16 | { 17 | #region Fields (2) 18 | private HostApplication _Application; 19 | private BuildScriptHost _Host; 20 | #endregion 21 | 22 | 23 | 24 | 25 | 26 | #region Constructor (1) 27 | public AgentService(HostApplication application, BuildScriptHost host) 28 | { 29 | if (application == null) 30 | { 31 | throw new ArgumentNullException("application"); 32 | } 33 | if (host == null) 34 | { 35 | throw new ArgumentNullException("host"); 36 | } 37 | 38 | _Application = application; 39 | _Host = host; 40 | } 41 | #endregion 42 | 43 | 44 | 45 | 46 | 47 | #region Properties (1) 48 | public string CurrentTask { get; set; } 49 | #endregion 50 | 51 | 52 | 53 | 54 | 55 | #region Functions (7) 56 | //Events 57 | public void Start(IDictionary arguments) 58 | { 59 | string target = UptimeUtils.IsStartup() ? "Startup" : "Start"; 60 | 61 | if ((arguments != null) && arguments.ContainsKey("target") && !String.IsNullOrWhiteSpace(arguments["target"].ToString())) 62 | { 63 | target = arguments["target"].ToString(); 64 | } 65 | 66 | this.RunTarget(target, true); 67 | } 68 | 69 | public void Stop() 70 | { 71 | this.RunTarget("Stop", false); 72 | } 73 | 74 | public void Shutdown() 75 | { 76 | this.RunTarget("Shutdown", false); 77 | } 78 | 79 | public void Terminate() 80 | { 81 | this.RunTarget("Terminate", false); 82 | } 83 | 84 | 85 | 86 | //Run 87 | private IList GetArgs(string target) 88 | { 89 | var args = new List(); 90 | 91 | args.Add(@"./CakeBoss.Agent.cake"); 92 | 93 | if (!String.IsNullOrEmpty(target)) 94 | { 95 | args.Add("-target=" + target); 96 | } 97 | 98 | if (Type.GetType("Mono.Runtime") != null) 99 | { 100 | args.Add("-mono"); 101 | } 102 | 103 | args.Add("-experimental=true"); 104 | args.Add("-verbosity=verbose"); 105 | 106 | return args; 107 | } 108 | 109 | public bool RunTarget(string target, bool load) 110 | { 111 | this.CurrentTask = target; 112 | bool result; 113 | 114 | if (load) 115 | { 116 | IList args = this.GetArgs(target); 117 | 118 | result = _Application.Run(args); 119 | } 120 | else 121 | { 122 | CakeReport report = _Host.RunTarget(target); 123 | 124 | result = (report != null && !report.IsEmpty); 125 | } 126 | 127 | this.CurrentTask = ""; 128 | return result; 129 | } 130 | #endregion 131 | } 132 | } 133 | -------------------------------------------------------------------------------- /src/Cake.Host/NuGet/NuGetVersionUtilityAdapter.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Runtime.Versioning; 5 | using Cake.Core.IO.NuGet; 6 | using Cake.Core.IO.NuGet.Parsing; 7 | using NuGet; 8 | using IFrameworkTargetable = Cake.Core.IO.NuGet.IFrameworkTargetable; 9 | 10 | namespace Cake.Host.NuGet 11 | { 12 | /// 13 | /// Adapts NuGet's to , 14 | /// . 15 | /// 16 | public sealed class NuGetVersionUtilityAdapter : INuGetFrameworkCompatibilityFilter, IFrameworkNameParser 17 | { 18 | /// 19 | /// This function tries to normalize a string that represents framework version names 20 | /// (the name of a framework version-specific folder in a nuget package, i.e., "net451" or "net35") into 21 | /// something a framework name that the package manager understands. 22 | /// 23 | /// value to be parsed. 24 | /// 25 | /// A FrameworkName instance corresponding with the provided frameworkName token. 26 | /// When parsing is unsuccessful, returns a FrameworkName with an Identifier property of "Unsupported." 27 | /// 28 | /// when frameworkName is null. 29 | public FrameworkName ParseFrameworkName(string frameworkName) 30 | { 31 | if (frameworkName == null) 32 | { 33 | throw new ArgumentNullException("frameworkName"); 34 | } 35 | 36 | return VersionUtility.ParseFrameworkName(frameworkName); 37 | } 38 | 39 | /// 40 | /// Filters the provided list of items, returning only those items compatible with the given project framework. 41 | /// 42 | /// the type of items being filtered 43 | /// The project framework. 44 | /// The items. 45 | /// The compatible items. Empty if try is unsuccessful. 46 | /// 47 | /// projectFramework or items 48 | /// 49 | public IEnumerable GetCompatibleItems(FrameworkName projectFramework, IEnumerable items) 50 | where T : IFrameworkTargetable 51 | { 52 | if (projectFramework == null) 53 | { 54 | throw new ArgumentNullException("projectFramework"); 55 | } 56 | if (items == null) 57 | { 58 | throw new ArgumentNullException("items"); 59 | } 60 | 61 | var nugetItems = items.Select(item => new FrameworkTargetableWrapper(item)).ToArray(); 62 | IEnumerable> compatibleNugetItems; 63 | if (VersionUtility.TryGetCompatibleItems(projectFramework, nugetItems, out compatibleNugetItems)) 64 | { 65 | return compatibleNugetItems.Select(item => item.WrappedItem); 66 | } 67 | 68 | return Enumerable.Empty(); 69 | } 70 | 71 | private class FrameworkTargetableWrapper : global::NuGet.IFrameworkTargetable 72 | where T : IFrameworkTargetable 73 | { 74 | private readonly T _inner; 75 | 76 | public FrameworkTargetableWrapper(T inner) 77 | { 78 | _inner = inner; 79 | } 80 | 81 | public T WrappedItem 82 | { 83 | get { return _inner; } 84 | } 85 | 86 | public IEnumerable SupportedFrameworks 87 | { 88 | get { return _inner.SupportedFrameworks; } 89 | } 90 | } 91 | } 92 | } -------------------------------------------------------------------------------- /src/CakeBoss.Agent/Program.cs: -------------------------------------------------------------------------------- 1 | #region Using Statements 2 | using System.IO; 3 | using System.Diagnostics; 4 | using System.Collections.Generic; 5 | 6 | using Topshelf; 7 | 8 | using Serilog; 9 | using Serilog.Events; 10 | 11 | using LightInject; 12 | using Nancy.Hosting.Self; 13 | 14 | using CakeBoss.Host; 15 | #endregion 16 | 17 | 18 | 19 | namespace CakeBoss.Agent 20 | { 21 | class Program 22 | { 23 | #region Fields (2) 24 | public static IServiceContainer Container = null; 25 | public static NancyHost Host = null; 26 | #endregion 27 | 28 | 29 | 30 | 31 | static void Main(string[] args) 32 | { 33 | //Logging 34 | string logFile = @"./Logs/CakeBoss.Agent-{Date}.log"; 35 | 36 | if (!Debugger.IsAttached && Directory.Exists("C:/Logs/CakeBoss/")) 37 | { 38 | logFile = @"C:/Logs/CakeBoss/Agent-{Date}.log"; 39 | } 40 | 41 | Log.Logger = new LoggerConfiguration() 42 | .WriteTo.RollingFile(logFile) 43 | .WriteTo.ColoredConsole() 44 | .MinimumLevel.Verbose() 45 | .Filter.ByExcluding((LogEvent log) => 46 | { 47 | return log.MessageTemplate.Text.Contains("Configuration Result:") 48 | && log.Properties.Count > 0 49 | && log.Properties["0"].ToString().Contains("[Success] Name CakeBoss.Agent"); 50 | }) 51 | .CreateLogger(); 52 | 53 | 54 | 55 | //Container 56 | Program.Container = Program.CreateContainer(); 57 | 58 | 59 | 60 | //TopShelf 61 | HostFactory.Run(x => 62 | { 63 | //CommandLine Parameters 64 | IDictionary arguments = x.SelectPlatform(p => p 65 | .AddStringParameter("target")); 66 | 67 | 68 | 69 | //Methods 70 | x.Service(s => 71 | { 72 | s.ConstructUsing(name => Program.Container.GetInstance()); 73 | 74 | s.WhenStarted(ser => ser.Start(arguments)); 75 | s.WhenStopped(ser => ser.Stop()); 76 | s.WhenShutdown(ser => ser.Shutdown()); 77 | }); 78 | 79 | 80 | 81 | //Settings 82 | x.StartAutomatically(); 83 | x.EnableShutdown(); 84 | 85 | x.RunAsNetworkService(); 86 | 87 | x.SetDescription("Cake scripting agent for automating deployment tasks"); 88 | x.SetDisplayName("CakeBoss - Agent"); 89 | x.SetServiceName("CakeBoss.Agent"); 90 | 91 | x.UseSerilog(Log.Logger); 92 | 93 | 94 | 95 | //Recovery 96 | x.EnableServiceRecovery(r => 97 | { 98 | //Actions 99 | r.RestartService(0); 100 | r.RestartService(1); 101 | r.RestartService(2); 102 | 103 | //Settings 104 | r.OnCrashOnly(); 105 | r.SetResetPeriod(1); 106 | }); 107 | }); 108 | } 109 | 110 | 111 | 112 | public static IServiceContainer CreateContainer() 113 | { 114 | var container = new ServiceContainer(); 115 | 116 | container.EnableAnnotatedPropertyInjection(); 117 | 118 | container.RegisterFrom(); 119 | container.RegisterFrom(); 120 | 121 | CakeContextExtensions.Container = container; 122 | 123 | return container; 124 | } 125 | } 126 | } 127 | -------------------------------------------------------------------------------- /src/Cake.Host/Scripting/Roslyn/Stable/RoslynScriptSessionFactory.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Reflection; 3 | using Cake.Core; 4 | using Cake.Core.Diagnostics; 5 | using Cake.Core.Scripting; 6 | using NuGet; 7 | 8 | namespace Cake.Host.Scripting.Roslyn.Stable 9 | { 10 | using Cake.Core.IO; 11 | 12 | public sealed class RoslynScriptSessionFactory 13 | { 14 | private readonly IFileSystem _fileSystem; 15 | private readonly ICakeEnvironment _environment; 16 | private readonly ICakeLog _log; 17 | private readonly FilePath[] _paths; 18 | 19 | public RoslynScriptSessionFactory( 20 | IFileSystem fileSystem, 21 | ICakeEnvironment environment, 22 | ICakeLog log) 23 | { 24 | _fileSystem = fileSystem; 25 | _environment = environment; 26 | _log = log; 27 | 28 | _paths = new FilePath[] 29 | { 30 | @"Roslyn.Compilers.CSharp.1.2.20906.2\lib\net45\Roslyn.Compilers.CSharp.dll", 31 | @"Roslyn.Compilers.Common.1.2.20906.2\lib\net45\Roslyn.Compilers.dll" 32 | }; 33 | } 34 | 35 | public IScriptSession CreateSession(IScriptHost host) 36 | { 37 | var root = _environment.GetApplicationRoot(); 38 | 39 | // Is Roslyn installed? 40 | if (!IsInstalled(root)) 41 | { 42 | _log.Information("Downloading and installing Roslyn..."); 43 | Install(root); 44 | } 45 | 46 | // Load Roslyn assemblies dynamically. 47 | foreach (var filePath in _paths) 48 | { 49 | Assembly.LoadFrom(_environment 50 | .GetApplicationRoot() 51 | .CombineWithFilePath(filePath.GetFilename()) 52 | .FullPath); 53 | } 54 | 55 | // Create a new session. 56 | return new RoslynScriptSession(host, _log); 57 | } 58 | 59 | private bool IsInstalled(DirectoryPath root) 60 | { 61 | if (root == null) 62 | { 63 | throw new ArgumentNullException("root"); 64 | } 65 | foreach (var path in _paths) 66 | { 67 | var filename = path.GetFilename(); 68 | var file = _fileSystem.GetFile(root.CombineWithFilePath(filename)); 69 | if (!file.Exists) 70 | { 71 | return false; 72 | } 73 | } 74 | return true; 75 | } 76 | 77 | private void Install(DirectoryPath root) 78 | { 79 | if (root == null) 80 | { 81 | throw new ArgumentNullException("root"); 82 | } 83 | 84 | var installRoot = root.Combine(Guid.NewGuid().ToString().Replace("-", string.Empty)); 85 | 86 | // Install package. 87 | _log.Verbose("Installing package..."); 88 | var repository = PackageRepositoryFactory.Default.CreateRepository("https://packages.nuget.org/api/v2"); 89 | var packageManager = new PackageManager(repository, installRoot.FullPath); 90 | packageManager.InstallPackage("Roslyn.Compilers.CSharp", new SemanticVersion(new Version(1, 2, 20906, 2)), false, true); 91 | 92 | // Copy files 93 | _log.Verbose("Copying files..."); 94 | foreach (var path in _paths) 95 | { 96 | var source = _fileSystem.GetFile(installRoot.CombineWithFilePath(path)); 97 | var destination = _fileSystem.GetFile(root.CombineWithFilePath(path.GetFilename())); 98 | 99 | _log.Information("Copying {0}...", source.Path.GetFilename()); 100 | 101 | if (!destination.Exists) 102 | { 103 | source.Copy(destination.Path, true); 104 | } 105 | } 106 | 107 | // Delete the install directory. 108 | _log.Verbose("Deleting installation directory..."); 109 | _fileSystem.GetDirectory(installRoot).Delete(true); 110 | } 111 | } 112 | } -------------------------------------------------------------------------------- /src/Cake.Host/Scripting/Mono/MonoScriptSession.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Linq; 3 | using System.Reflection; 4 | using Cake.Core; 5 | using Cake.Core.Diagnostics; 6 | using Cake.Core.IO; 7 | using Cake.Core.Scripting; 8 | using Cake.Host.Scripting.Mono.CodeGen; 9 | using Mono.CSharp; 10 | 11 | namespace Cake.Host.Scripting.Mono 12 | { 13 | public sealed class MonoScriptSession : IScriptSession 14 | { 15 | private readonly Evaluator _evaluator; 16 | private readonly ICakeLog _log; 17 | 18 | private readonly string[] _skipAssemblies = 19 | { 20 | "mscorlib", 21 | "System", 22 | "System.Core" 23 | }; 24 | 25 | public MonoScriptSession(IScriptHost host, ICakeLog log) 26 | { 27 | if (host == null) 28 | { 29 | throw new ArgumentNullException("host"); 30 | } 31 | if (log == null) 32 | { 33 | throw new ArgumentNullException("log"); 34 | } 35 | 36 | _log = log; 37 | 38 | // Create the evaluator. 39 | var compilerSettings = new CompilerSettings(); 40 | var reportPrinter = new MonoConsoleReportPrinter(_log); 41 | var compilerContext = new CompilerContext(compilerSettings, reportPrinter); 42 | _evaluator = new Evaluator(compilerContext); 43 | 44 | // Set our instance of the script host to this static member 45 | MonoScriptHostProxy.ScriptHost = host; 46 | 47 | // This will be our 'base' type from which the evaluator grants access 48 | // to static members to the script being run 49 | _evaluator.InteractiveBaseClass = typeof(MonoScriptHostProxy); 50 | } 51 | 52 | public void AddReference(FilePath path) 53 | { 54 | if (path == null) 55 | { 56 | throw new ArgumentNullException("path"); 57 | } 58 | _log.Debug("Adding reference to {0}...", path.FullPath); 59 | _evaluator.ReferenceAssembly(Assembly.LoadFrom(path.FullPath)); 60 | } 61 | 62 | public void AddReference(Assembly assembly) 63 | { 64 | if (assembly == null) 65 | { 66 | throw new ArgumentNullException("assembly"); 67 | } 68 | 69 | var name = assembly.GetName().Name; 70 | 71 | // We don't need to load these ones as they will already get loaded by Mono.CSharp 72 | if (_skipAssemblies.Contains(name)) 73 | { 74 | return; 75 | } 76 | 77 | _log.Debug("Adding reference to {0}...", new FilePath(assembly.Location).GetFilename().FullPath); 78 | _evaluator.ReferenceAssembly(assembly); 79 | } 80 | 81 | public void ImportNamespace(string @namespace) 82 | { 83 | _log.Debug("Importing namespace {0}...", @namespace); 84 | _evaluator.Run("using " + @namespace + ";"); 85 | } 86 | 87 | public void Execute(Script script) 88 | { 89 | if (script == null) 90 | { 91 | throw new ArgumentNullException("script"); 92 | } 93 | 94 | if (script.UsingAliasDirectives.Count > 0) 95 | { 96 | throw new CakeException("The Mono scripting engine do not support using alias directives."); 97 | } 98 | 99 | var code = MonoCodeGenerator.Generate(script); 100 | 101 | try 102 | { 103 | // Build the class we generated. 104 | _log.Verbose("Compiling build script..."); 105 | _evaluator.Run(code); 106 | 107 | // Actually execute it. 108 | _evaluator.Run("new CakeBuildScriptImpl (ScriptHost).Execute ();"); 109 | } 110 | catch (InternalErrorException) 111 | { 112 | // The error will be logged via the report printer. 113 | throw new CakeException("An error occured while executing build script."); 114 | } 115 | } 116 | } 117 | } -------------------------------------------------------------------------------- /src/Cake.Host/Diagnostics/Formatting/FormatParser.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Globalization; 4 | using System.IO; 5 | using System.Linq; 6 | using System.Text; 7 | 8 | namespace Cake.Host.Diagnostics.Formatting 9 | { 10 | public static class FormatParser 11 | { 12 | public static IEnumerable Parse(string format) 13 | { 14 | var reader = new StringReader(format); 15 | while (true) 16 | { 17 | var current = reader.Peek(); 18 | if (current == -1) 19 | { 20 | break; 21 | } 22 | var character = (char)current; 23 | if (character == '{') 24 | { 25 | yield return ParseProperty(reader); 26 | } 27 | else 28 | { 29 | yield return ParseText(reader); 30 | } 31 | } 32 | } 33 | 34 | private static FormatToken ParseProperty(TextReader reader) 35 | { 36 | reader.Read(); // Consume 37 | if (reader.Peek() == -1) 38 | { 39 | return new LiteralToken("{"); 40 | } 41 | if ((char)reader.Peek() == '{') 42 | { 43 | reader.Read(); 44 | return new LiteralToken("{{"); 45 | } 46 | var builder = new StringBuilder(); 47 | while (true) 48 | { 49 | var current = reader.Peek(); 50 | if (current == -1) 51 | { 52 | break; 53 | } 54 | 55 | var character = (char)current; 56 | if (character == '}') 57 | { 58 | reader.Read(); 59 | 60 | var accumulated = builder.ToString(); 61 | var parts = accumulated.Split(new[] { ':' }, StringSplitOptions.None); 62 | if (parts.Length > 1) 63 | { 64 | var name = parts[0]; 65 | var format = string.Join(string.Empty, parts.Skip(1)); 66 | var positional = IsNumeric(name); 67 | if (!positional) 68 | { 69 | throw new FormatException("Input string was not in a correct format."); 70 | } 71 | var position = int.Parse(name, CultureInfo.InvariantCulture); 72 | return new PropertyToken(position, format); 73 | } 74 | else 75 | { 76 | var positional = IsNumeric(accumulated); 77 | if (!positional) 78 | { 79 | throw new FormatException("Input string was not in a correct format."); 80 | } 81 | var position = int.Parse(accumulated, CultureInfo.InvariantCulture); 82 | return new PropertyToken(position, null); 83 | } 84 | } 85 | builder.Append((char)reader.Read()); 86 | } 87 | return new LiteralToken(builder.ToString()); 88 | } 89 | 90 | private static FormatToken ParseText(TextReader reader) 91 | { 92 | var builder = new StringBuilder(); 93 | while (true) 94 | { 95 | var current = reader.Peek(); 96 | if (current == -1) 97 | { 98 | break; 99 | } 100 | var character = (char)current; 101 | if (character == '{') 102 | { 103 | break; 104 | } 105 | builder.Append((char)reader.Read()); 106 | } 107 | return new LiteralToken(builder.ToString()); 108 | } 109 | 110 | private static bool IsNumeric(string value) 111 | { 112 | if (string.IsNullOrWhiteSpace(value)) 113 | { 114 | return false; 115 | } 116 | foreach (var character in value) 117 | { 118 | if (!char.IsDigit(character)) 119 | { 120 | return false; 121 | } 122 | } 123 | return true; 124 | } 125 | } 126 | } -------------------------------------------------------------------------------- /src/Cake.Host/CakeApplication.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using Cake.Host.Arguments; 4 | using Cake.Host.Commands; 5 | using Cake.Core; 6 | using Cake.Core.Diagnostics; 7 | using Cake.Host.Diagnostics; 8 | 9 | namespace Cake.Host 10 | { 11 | /// 12 | /// The Cake.Host application. 13 | /// 14 | public sealed class CakeApplication 15 | { 16 | private readonly IVerbosityAwareLog _log; 17 | private readonly ICommandFactory _commandFactory; 18 | private readonly IArgumentParser _argumentParser; 19 | private readonly IConsole _console; 20 | 21 | /// 22 | /// Initializes a new instance of the class. 23 | /// 24 | /// The log. 25 | /// The command factory. 26 | /// The argument parser. 27 | /// The console. 28 | public CakeApplication( 29 | IVerbosityAwareLog log, 30 | ICommandFactory commandFactory, 31 | IArgumentParser argumentParser, 32 | IConsole console) 33 | { 34 | if (log == null) 35 | { 36 | throw new ArgumentNullException("log"); 37 | } 38 | if (commandFactory == null) 39 | { 40 | throw new ArgumentNullException("commandFactory"); 41 | } 42 | if (argumentParser == null) 43 | { 44 | throw new ArgumentNullException("argumentParser"); 45 | } 46 | if (console == null) 47 | { 48 | throw new ArgumentNullException("console"); 49 | } 50 | 51 | _log = log; 52 | _commandFactory = commandFactory; 53 | _argumentParser = argumentParser; 54 | _console = console; 55 | } 56 | 57 | /// 58 | /// Runs the application with the specified arguments. 59 | /// 60 | /// The arguments. 61 | /// The application exit code. 62 | public int Run(IEnumerable args) 63 | { 64 | try 65 | { 66 | // Parse options. 67 | var options = _argumentParser.Parse(args); 68 | if (options != null) 69 | { 70 | _log.SetVerbosity(options.Verbosity); 71 | } 72 | 73 | // Create the correct command and execute it. 74 | var command = CreateCommand(options); 75 | var result = command.Execute(options); 76 | 77 | // Return success if the command succeeded. 78 | // If the parsed options are null, or if the command failed, consider it failed. 79 | return options == null || result == false ? 1 : 0; 80 | } 81 | catch (Exception ex) 82 | { 83 | if (_log.Verbosity == Verbosity.Diagnostic) 84 | { 85 | _log.Error("Error: {0}", ex); 86 | } 87 | else 88 | { 89 | _log.Error("Error: {0}", ex.Message); 90 | } 91 | return 1; 92 | } 93 | } 94 | 95 | private ICommand CreateCommand(CakeOptions options) 96 | { 97 | if (options != null) 98 | { 99 | if (options.ShowHelp) 100 | { 101 | return _commandFactory.CreateHelpCommand(); 102 | } 103 | 104 | if (options.ShowVersion) 105 | { 106 | return _commandFactory.CreateVersionCommand(); 107 | } 108 | 109 | if (options.Script != null) 110 | { 111 | if (options.PerformDryRun) 112 | { 113 | return _commandFactory.CreateDryRunCommand(); 114 | } 115 | 116 | if (options.ShowDescription) 117 | { 118 | _log.SetVerbosity(options.Verbosity); 119 | return _commandFactory.CreateDescriptionCommand(); 120 | } 121 | 122 | return _commandFactory.CreateBuildCommand(); 123 | } 124 | } 125 | 126 | _console.WriteLine(); 127 | _log.Error("Could not find a build script to execute."); 128 | _log.Error("Either the first argument must the build script's path,"); 129 | _log.Error("or build script should follow default script name conventions."); 130 | 131 | return new ErrorCommandDecorator(_commandFactory.CreateHelpCommand()); 132 | } 133 | } 134 | } -------------------------------------------------------------------------------- /src/CakeBoss.Host/Console/HostLog.cs: -------------------------------------------------------------------------------- 1 | #region Using Statements 2 | using System; 3 | using System.Diagnostics; 4 | using System.Collections.Generic; 5 | 6 | using Cake.Core; 7 | using Cake.Core.Diagnostics; 8 | using Cake.Host.Diagnostics; 9 | using Cake.Host.Diagnostics.Formatting; 10 | 11 | using Serilog; 12 | using Serilog.Events; 13 | #endregion 14 | 15 | 16 | 17 | namespace CakeBoss.Host 18 | { 19 | public sealed class HostLog : IVerbosityAwareLog 20 | { 21 | #region Fields (3) 22 | private readonly IConsole _console; 23 | private readonly object _lock; 24 | private readonly IDictionary _palettes; 25 | #endregion 26 | 27 | 28 | 29 | 30 | 31 | #region Constructor (1) 32 | public HostLog(IConsole console) 33 | { 34 | _console = console; 35 | _lock = new object(); 36 | _palettes = CreatePalette(); 37 | Verbosity = Debugger.IsAttached ? Verbosity.Diagnostic : Verbosity.Normal; 38 | } 39 | #endregion 40 | 41 | 42 | 43 | 44 | 45 | #region Properties (1) 46 | public Verbosity Verbosity { get; private set; } 47 | #endregion 48 | 49 | 50 | 51 | 52 | 53 | #region Functions (1) 54 | public void Write(Verbosity verbosity, LogLevel level, string format, params object[] args) 55 | { 56 | if (verbosity > Verbosity) 57 | { 58 | return; 59 | } 60 | lock (_lock) 61 | { 62 | try 63 | { 64 | var palette = _palettes[level]; 65 | var tokens = FormatParser.Parse(format); 66 | foreach (var token in tokens) 67 | { 68 | SetPalette(token, palette); 69 | _console.Write("{0}", token.Render(args)); 70 | } 71 | 72 | Log.Logger.Write(this.GetLogLevel(level), format, args); 73 | } 74 | finally 75 | { 76 | _console.ResetColor(); 77 | _console.WriteLine(); 78 | } 79 | } 80 | } 81 | 82 | public void SetVerbosity(Verbosity verbosity) 83 | { 84 | Verbosity = verbosity; 85 | } 86 | 87 | private void SetPalette(FormatToken token, ConsolePalette palette) 88 | { 89 | var property = token as PropertyToken; 90 | if (property != null) 91 | { 92 | _console.BackgroundColor = palette.ArgumentBackground; 93 | _console.ForegroundColor = palette.ArgumentForeground; 94 | } 95 | else 96 | { 97 | _console.BackgroundColor = palette.Background; 98 | _console.ForegroundColor = palette.Foreground; 99 | } 100 | } 101 | 102 | 103 | 104 | private IDictionary CreatePalette() 105 | { 106 | var background = _console.BackgroundColor; 107 | var palette = new Dictionary 108 | { 109 | { LogLevel.Error, new ConsolePalette(ConsoleColor.DarkRed, ConsoleColor.White, ConsoleColor.Red, ConsoleColor.White) }, 110 | { LogLevel.Warning, new ConsolePalette(background, ConsoleColor.Yellow, background, ConsoleColor.Yellow) }, 111 | { LogLevel.Information, new ConsolePalette(background, ConsoleColor.White, ConsoleColor.DarkBlue, ConsoleColor.White) }, 112 | { LogLevel.Verbose, new ConsolePalette(background, ConsoleColor.Gray, background, ConsoleColor.White) }, 113 | { LogLevel.Debug, new ConsolePalette(background, ConsoleColor.DarkGray, background, ConsoleColor.Gray) } 114 | }; 115 | return palette; 116 | } 117 | 118 | private LogEventLevel GetLogLevel(LogLevel level) 119 | { 120 | switch (level) 121 | { 122 | case LogLevel.Fatal: 123 | return LogEventLevel.Fatal; 124 | 125 | case LogLevel.Error: 126 | return LogEventLevel.Error; 127 | 128 | case LogLevel.Warning: 129 | return LogEventLevel.Warning; 130 | 131 | case LogLevel.Information: 132 | return LogEventLevel.Information; 133 | 134 | case LogLevel.Verbose: 135 | return LogEventLevel.Verbose; 136 | } 137 | 138 | return LogEventLevel.Debug; 139 | } 140 | #endregion 141 | } 142 | } 143 | -------------------------------------------------------------------------------- /src/CakeBoss.sln: -------------------------------------------------------------------------------- 1 | 2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio 14 4 | VisualStudioVersion = 14.0.24720.0 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Build", "Build", "{805059EC-6CC4-418B-B0ED-E40A21145526}" 7 | ProjectSection(SolutionItems) = preProject 8 | ..\.gitignore = ..\.gitignore 9 | ..\appveyor.yml = ..\appveyor.yml 10 | ..\build.cake = ..\build.cake 11 | ..\build.ps1 = ..\build.ps1 12 | EndProjectSection 13 | EndProject 14 | Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Source", "Source", "{EA42D027-E363-4943-ABED-1F3C37FD6CA5}" 15 | EndProject 16 | Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Docs", "Docs", "{23704DC0-E2D6-47C3-9E11-2A1D8E497980}" 17 | ProjectSection(SolutionItems) = preProject 18 | ..\LICENSE = ..\LICENSE 19 | ..\README.md = ..\README.md 20 | ..\ReleaseNotes.md = ..\ReleaseNotes.md 21 | EndProjectSection 22 | EndProject 23 | Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Script", "Script", "{567027D0-0823-4B53-9FD2-E1FB020DAAD9}" 24 | ProjectSection(SolutionItems) = preProject 25 | ..\script\Release.cake = ..\script\Release.cake 26 | ..\script\Test.cake = ..\script\Test.cake 27 | EndProjectSection 28 | EndProject 29 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Cake.CakeBoss", "Cake.CakeBoss\Cake.CakeBoss.csproj", "{8C311438-E0F0-4A47-AC31-DA29BF901FB2}" 30 | EndProject 31 | Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Cake", "Cake", "{4E7C9059-8E12-4AC4-85E4-C6B0F5CDD339}" 32 | EndProject 33 | Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "CakeBoss", "CakeBoss", "{00965049-79EF-4B11-9A6F-7A60A2E96977}" 34 | EndProject 35 | Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Tests", "Tests", "{22F59941-5BFC-46E9-B683-41DFCABC94FE}" 36 | EndProject 37 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CakeBoss.Host", "CakeBoss.Host\CakeBoss.Host.csproj", "{206F12ED-5FFA-4333-A5A9-31C142648AC1}" 38 | EndProject 39 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CakeBoss.Agent", "CakeBoss.Agent\CakeBoss.Agent.csproj", "{14449D2A-6115-476B-8F8A-78A1BF726299}" 40 | EndProject 41 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CakeBoss.Agent.Tests", "CakeBoss.Agent.Tests\CakeBoss.Agent.Tests.csproj", "{86E04045-FE0D-4EB4-85C1-8B7792B4C4E3}" 42 | EndProject 43 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Cake.Host", "Cake.Host\Cake.Host.csproj", "{C29AF03C-36E0-4161-B28F-B114C2555E7B}" 44 | EndProject 45 | Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Nuget", "Nuget", "{EF82BC0D-0B54-4BBC-9D18-92435B03AC50}" 46 | ProjectSection(SolutionItems) = preProject 47 | ..\nuspec\Cake.CakeBoss.nuspec = ..\nuspec\Cake.CakeBoss.nuspec 48 | EndProjectSection 49 | EndProject 50 | Global 51 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 52 | Debug|Any CPU = Debug|Any CPU 53 | Release|Any CPU = Release|Any CPU 54 | EndGlobalSection 55 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 56 | {8C311438-E0F0-4A47-AC31-DA29BF901FB2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 57 | {8C311438-E0F0-4A47-AC31-DA29BF901FB2}.Debug|Any CPU.Build.0 = Debug|Any CPU 58 | {8C311438-E0F0-4A47-AC31-DA29BF901FB2}.Release|Any CPU.ActiveCfg = Release|Any CPU 59 | {8C311438-E0F0-4A47-AC31-DA29BF901FB2}.Release|Any CPU.Build.0 = Release|Any CPU 60 | {206F12ED-5FFA-4333-A5A9-31C142648AC1}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 61 | {206F12ED-5FFA-4333-A5A9-31C142648AC1}.Debug|Any CPU.Build.0 = Debug|Any CPU 62 | {206F12ED-5FFA-4333-A5A9-31C142648AC1}.Release|Any CPU.ActiveCfg = Release|Any CPU 63 | {206F12ED-5FFA-4333-A5A9-31C142648AC1}.Release|Any CPU.Build.0 = Release|Any CPU 64 | {14449D2A-6115-476B-8F8A-78A1BF726299}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 65 | {14449D2A-6115-476B-8F8A-78A1BF726299}.Debug|Any CPU.Build.0 = Debug|Any CPU 66 | {14449D2A-6115-476B-8F8A-78A1BF726299}.Release|Any CPU.ActiveCfg = Release|Any CPU 67 | {14449D2A-6115-476B-8F8A-78A1BF726299}.Release|Any CPU.Build.0 = Release|Any CPU 68 | {86E04045-FE0D-4EB4-85C1-8B7792B4C4E3}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 69 | {86E04045-FE0D-4EB4-85C1-8B7792B4C4E3}.Debug|Any CPU.Build.0 = Debug|Any CPU 70 | {86E04045-FE0D-4EB4-85C1-8B7792B4C4E3}.Release|Any CPU.ActiveCfg = Release|Any CPU 71 | {86E04045-FE0D-4EB4-85C1-8B7792B4C4E3}.Release|Any CPU.Build.0 = Release|Any CPU 72 | {C29AF03C-36E0-4161-B28F-B114C2555E7B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 73 | {C29AF03C-36E0-4161-B28F-B114C2555E7B}.Debug|Any CPU.Build.0 = Debug|Any CPU 74 | {C29AF03C-36E0-4161-B28F-B114C2555E7B}.Release|Any CPU.ActiveCfg = Release|Any CPU 75 | {C29AF03C-36E0-4161-B28F-B114C2555E7B}.Release|Any CPU.Build.0 = Release|Any CPU 76 | EndGlobalSection 77 | GlobalSection(SolutionProperties) = preSolution 78 | HideSolutionNode = FALSE 79 | EndGlobalSection 80 | GlobalSection(NestedProjects) = preSolution 81 | {8C311438-E0F0-4A47-AC31-DA29BF901FB2} = {4E7C9059-8E12-4AC4-85E4-C6B0F5CDD339} 82 | {4E7C9059-8E12-4AC4-85E4-C6B0F5CDD339} = {EA42D027-E363-4943-ABED-1F3C37FD6CA5} 83 | {00965049-79EF-4B11-9A6F-7A60A2E96977} = {EA42D027-E363-4943-ABED-1F3C37FD6CA5} 84 | {22F59941-5BFC-46E9-B683-41DFCABC94FE} = {EA42D027-E363-4943-ABED-1F3C37FD6CA5} 85 | {206F12ED-5FFA-4333-A5A9-31C142648AC1} = {00965049-79EF-4B11-9A6F-7A60A2E96977} 86 | {14449D2A-6115-476B-8F8A-78A1BF726299} = {00965049-79EF-4B11-9A6F-7A60A2E96977} 87 | {86E04045-FE0D-4EB4-85C1-8B7792B4C4E3} = {22F59941-5BFC-46E9-B683-41DFCABC94FE} 88 | {C29AF03C-36E0-4161-B28F-B114C2555E7B} = {4E7C9059-8E12-4AC4-85E4-C6B0F5CDD339} 89 | EndGlobalSection 90 | EndGlobal 91 | -------------------------------------------------------------------------------- /src/CakeBoss.Host/Host/HostApplication.cs: -------------------------------------------------------------------------------- 1 | #region Using Statements 2 | using System; 3 | using System.Collections.Generic; 4 | 5 | using Cake.Host; 6 | using Cake.Host.Commands; 7 | using Cake.Core; 8 | using Cake.Host.Arguments; 9 | using Cake.Core.Diagnostics; 10 | using Cake.Host.Diagnostics; 11 | #endregion 12 | 13 | 14 | 15 | namespace CakeBoss.Host 16 | { 17 | /// 18 | /// The Cake application. 19 | /// 20 | public sealed class HostApplication 21 | { 22 | #region Fields (4) 23 | private readonly IVerbosityAwareLog _log; 24 | private readonly ICommandFactory _commandFactory; 25 | private readonly IArgumentParser _argumentParser; 26 | private readonly IConsole _console; 27 | #endregion 28 | 29 | 30 | 31 | 32 | 33 | #region Constructor (1) 34 | /// 35 | /// Initializes a new instance of the class. 36 | /// 37 | /// The log. 38 | /// The command factory. 39 | /// The argument parser. 40 | /// The console. 41 | public HostApplication( 42 | IVerbosityAwareLog log, 43 | ICommandFactory commandFactory, 44 | IArgumentParser argumentParser, 45 | IConsole console) 46 | { 47 | if (log == null) 48 | { 49 | throw new ArgumentNullException("log"); 50 | } 51 | if (commandFactory == null) 52 | { 53 | throw new ArgumentNullException("commandFactory"); 54 | } 55 | if (argumentParser == null) 56 | { 57 | throw new ArgumentNullException("argumentParser"); 58 | } 59 | if (console == null) 60 | { 61 | throw new ArgumentNullException("console"); 62 | } 63 | 64 | _log = log; 65 | _commandFactory = commandFactory; 66 | _argumentParser = argumentParser; 67 | _console = console; 68 | } 69 | #endregion 70 | 71 | 72 | 73 | 74 | 75 | #region Functions (2) 76 | /// 77 | /// Runs the application with the specified arguments. 78 | /// 79 | /// The arguments. 80 | /// The application exit code. 81 | public bool Run(IEnumerable args) 82 | { 83 | try 84 | { 85 | // Parse options. 86 | var options = _argumentParser.Parse(args); 87 | if (options != null) 88 | { 89 | _log.SetVerbosity(options.Verbosity); 90 | } 91 | 92 | // Create the correct command and execute it. 93 | var command = this.CreateCommand(options); 94 | return command.Execute(options); 95 | } 96 | catch (Exception ex) 97 | { 98 | if (_log.Verbosity == Verbosity.Diagnostic) 99 | { 100 | _log.Error("Error: {0}", ex); 101 | } 102 | else 103 | { 104 | _log.Error("Error: {0}", ex.Message); 105 | } 106 | 107 | return false; 108 | } 109 | } 110 | 111 | public ICommand CreateCommand(CakeOptions options) 112 | { 113 | if (options != null) 114 | { 115 | if (options.ShowHelp) 116 | { 117 | return _commandFactory.CreateHelpCommand(); 118 | } 119 | 120 | if (options.ShowVersion) 121 | { 122 | return _commandFactory.CreateVersionCommand(); 123 | } 124 | 125 | if (options.Script != null) 126 | { 127 | if (options.PerformDryRun) 128 | { 129 | return _commandFactory.CreateDryRunCommand(); 130 | } 131 | 132 | if (options.ShowDescription) 133 | { 134 | _log.SetVerbosity(options.Verbosity); 135 | return _commandFactory.CreateDescriptionCommand(); 136 | } 137 | 138 | return _commandFactory.CreateBuildCommand(); 139 | } 140 | } 141 | 142 | _console.WriteLine(); 143 | _log.Error("Could not find a build script to execute."); 144 | _log.Error("Either the first argument must the build script's path,"); 145 | _log.Error("or build script should follow default script name conventions."); 146 | 147 | return new ErrorCommandDecorator(_commandFactory.CreateHelpCommand()); 148 | } 149 | #endregion 150 | } 151 | } 152 | -------------------------------------------------------------------------------- /src/Cake.Host/Scripting/Roslyn/Nightly/RoslynNightlyScriptSessionFactory.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Globalization; 4 | using System.Linq; 5 | using System.Reflection; 6 | using Cake.Core; 7 | using Cake.Core.Diagnostics; 8 | using Cake.Core.Scripting; 9 | using NuGet; 10 | 11 | namespace Cake.Host.Scripting.Roslyn.Nightly 12 | { 13 | using Cake.Core.IO; 14 | 15 | public sealed class RoslynNightlyScriptSessionFactory 16 | { 17 | private readonly IFileSystem _fileSystem; 18 | private readonly ICakeEnvironment _environment; 19 | private readonly IGlobber _globber; 20 | private readonly ICakeLog _log; 21 | private readonly FilePath[] _paths; 22 | 23 | public RoslynNightlyScriptSessionFactory( 24 | IFileSystem fileSystem, 25 | ICakeEnvironment environment, 26 | IGlobber globber, 27 | ICakeLog log) 28 | { 29 | _fileSystem = fileSystem; 30 | _environment = environment; 31 | _globber = globber; 32 | _log = log; 33 | 34 | _paths = new FilePath[] 35 | { 36 | @"net45/Microsoft.CodeAnalysis.dll", 37 | @"net45/Microsoft.CodeAnalysis.Scripting.CSharp.dll", 38 | @"net45/Microsoft.CodeAnalysis.Scripting.dll", 39 | @"net45/Microsoft.CodeAnalysis.Desktop.dll", 40 | @"net45/Microsoft.CodeAnalysis.CSharp.dll", 41 | @"net45/Microsoft.CodeAnalysis.CSharp.Desktop.dll", 42 | @"portable-net45+win8+wp8+wpa81/System.Collections.Immutable.dll", 43 | @"portable-net45+win8/System.Reflection.Metadata.dll", 44 | }; 45 | } 46 | 47 | public IScriptSession CreateSession(IScriptHost host) 48 | { 49 | // Is Roslyn installed? 50 | if (!IsInstalled()) 51 | { 52 | _log.Information("Downloading and installing Roslyn (experimental)..."); 53 | Install(new SemanticVersion(1, 0, 0, "rc2")); 54 | } 55 | 56 | // Load Roslyn assemblies dynamically. 57 | foreach (var filePath in _paths) 58 | { 59 | Assembly.LoadFrom(_environment 60 | .GetApplicationRoot() 61 | .CombineWithFilePath(filePath.GetFilename()) 62 | .FullPath); 63 | } 64 | 65 | // Create the session. 66 | return new RoslynNightlyScriptSession(host, _log); 67 | } 68 | 69 | private bool IsInstalled() 70 | { 71 | var root = _environment.GetApplicationRoot(); 72 | foreach (var path in _paths) 73 | { 74 | var filename = path.GetFilename(); 75 | var file = _fileSystem.GetFile(root.CombineWithFilePath(filename)); 76 | if (!file.Exists) 77 | { 78 | return false; 79 | } 80 | } 81 | return true; 82 | } 83 | 84 | private void Install(SemanticVersion version) 85 | { 86 | var root = _environment.GetApplicationRoot().MakeAbsolute(_environment); 87 | var installRoot = root.MakeAbsolute(_environment).Combine(Guid.NewGuid().ToString("N", CultureInfo.InvariantCulture)); 88 | 89 | var packages = new Dictionary 90 | { 91 | { "Microsoft.CodeAnalysis.Scripting", version }, 92 | { "Microsoft.CodeAnalysis.CSharp", version } 93 | }; 94 | 95 | // Install package. 96 | _log.Verbose("Installing packages..."); 97 | var packageManager = CreatePackageManager(installRoot); 98 | foreach (var package in packages) 99 | { 100 | _log.Information("Downloading package {0} ({1})...", package.Key, package.Value); 101 | packageManager.InstallPackage(package.Key, package.Value, false, true); 102 | } 103 | 104 | // Copy files. 105 | _log.Verbose("Copying files..."); 106 | foreach (var path in _paths) 107 | { 108 | // Find the file within the temporary directory. 109 | var exp = string.Concat(installRoot.FullPath, "/**/", path); 110 | var foundFile = _globber.Match(exp).FirstOrDefault(); 111 | if (foundFile == null) 112 | { 113 | var format = "Could not find file {0}."; 114 | var message = string.Format(CultureInfo.InvariantCulture, format, path); 115 | throw new CakeException(message); 116 | } 117 | 118 | var source = _fileSystem.GetFile((FilePath)foundFile); 119 | var destination = _fileSystem.GetFile(root.CombineWithFilePath(path.GetFilename())); 120 | 121 | _log.Information("Copying {0}...", source.Path.GetFilename()); 122 | 123 | if (!destination.Exists) 124 | { 125 | source.Copy(destination.Path, true); 126 | } 127 | } 128 | 129 | // Delete the install directory. 130 | _log.Verbose("Deleting installation directory..."); 131 | _fileSystem.GetDirectory(installRoot).Delete(true); 132 | } 133 | 134 | private static IPackageManager CreatePackageManager(DirectoryPath path) 135 | { 136 | var sources = new[] 137 | { 138 | new PackageSource("https://packages.nuget.org/api/v2"), 139 | }; 140 | var repo = AggregateRepository.Create(PackageRepositoryFactory.Default, sources, false); 141 | return new PackageManager(repo, path.FullPath); 142 | } 143 | } 144 | } -------------------------------------------------------------------------------- /src/CakeBoss.Host/Console/HostConsole.cs: -------------------------------------------------------------------------------- 1 | #region Using Statements 2 | using System; 3 | using System.Collections.Generic; 4 | 5 | using Serilog; 6 | using Cake.Core; 7 | #endregion 8 | 9 | 10 | 11 | namespace CakeBoss.Host 12 | { 13 | public sealed class HostConsole : IConsole 14 | { 15 | #region Fields (3) 16 | private ConsoleColor _ForegroundColor; 17 | private ConsoleColor _BackgroundColor; 18 | 19 | private IList _Output; 20 | #endregion 21 | 22 | 23 | 24 | 25 | 26 | #region Constructor (1) 27 | public HostConsole() 28 | { 29 | _Output = new List(); 30 | 31 | this.ResetColor(); 32 | } 33 | #endregion 34 | 35 | 36 | 37 | 38 | 39 | #region Properties (2) 40 | /// 41 | /// Gets or sets the foreground color. 42 | /// 43 | /// The foreground color. 44 | public ConsoleColor ForegroundColor 45 | { 46 | get 47 | { 48 | return _ForegroundColor; 49 | } 50 | set 51 | { 52 | _ForegroundColor = value; 53 | } 54 | } 55 | 56 | /// 57 | /// Gets or sets the background color. 58 | /// 59 | /// The background color. 60 | public ConsoleColor BackgroundColor 61 | { 62 | get 63 | { 64 | return _BackgroundColor; 65 | } 66 | set 67 | { 68 | _BackgroundColor = value; 69 | } 70 | } 71 | #endregion 72 | 73 | 74 | 75 | 76 | 77 | #region Functions (4) 78 | /// 79 | /// Writes the text representation of the specified array of objects to the 80 | /// console output using the specified format information. 81 | /// 82 | /// A composite format string 83 | /// An array of objects to write using format. 84 | public void Write(string format, params object[] arg) 85 | { 86 | this.CreateOutput(String.Format(format, arg), this.ForegroundColor); 87 | } 88 | 89 | /// 90 | /// Writes the text representation of the specified array of objects, followed 91 | /// by the current line terminator, to the console output using the specified 92 | /// format information. 93 | /// 94 | /// A composite format string 95 | /// An array of objects to write using format. 96 | public void WriteLine(string format, params object[] arg) 97 | { 98 | this.CreateOutput(String.Format(format, arg) + Environment.NewLine, this.ForegroundColor); 99 | } 100 | 101 | 102 | 103 | /// 104 | /// Writes the text representation of the specified array of objects to the 105 | /// console output using the specified format information. 106 | /// 107 | /// A composite format string 108 | /// An array of objects to write using format. 109 | public void WriteError(string format, params object[] arg) 110 | { 111 | this.CreateOutput(String.Format(format, arg) + Environment.NewLine, ConsoleColor.Red); 112 | } 113 | 114 | /// 115 | /// Writes the text representation of the specified array of objects, followed 116 | /// by the current line terminator, to the console output using the specified 117 | /// format information. 118 | /// 119 | /// A composite format string 120 | /// An array of objects to write using format. 121 | public void WriteErrorLine(string format, params object[] arg) 122 | { 123 | this.CreateOutput(String.Format(format, arg) + Environment.NewLine, this.ForegroundColor); 124 | } 125 | 126 | 127 | 128 | /// 129 | /// Sets the foreground and background console colors to their defaults. 130 | /// 131 | public void ResetColor() 132 | { 133 | _ForegroundColor = ConsoleColor.White; 134 | _BackgroundColor = ConsoleColor.DarkBlue; 135 | } 136 | 137 | 138 | 139 | private void CreateOutput(string text, ConsoleColor color) 140 | { 141 | /*if (!String.IsNullOrEmpty(text)) 142 | { 143 | //Format 144 | text = text.Replace(Environment.NewLine + Environment.NewLine, Environment.NewLine); 145 | 146 | //Build 147 | ConsoleOutput output = new ConsoleOutput(text, color); 148 | _Output.Add(output); 149 | 150 | //Flush 151 | if (text.Contains(Environment.NewLine)) 152 | { 153 | string info = ""; 154 | 155 | foreach (ConsoleOutput part in _Output) 156 | { 157 | info += part.Text; 158 | } 159 | 160 | Log.Logger.Information(info); 161 | _Output.Clear(); 162 | } 163 | }*/ 164 | } 165 | #endregion 166 | } 167 | } 168 | -------------------------------------------------------------------------------- /src/CakeBoss.Host/Registry/HostRoot.cs: -------------------------------------------------------------------------------- 1 | #region Using Statements 2 | using System; 3 | 4 | using Cake.Host; 5 | using Cake.Host.Arguments; 6 | using Cake.Host.Commands; 7 | using Cake.Core; 8 | using Cake.Core.Diagnostics; 9 | using Cake.Core.IO; 10 | using Cake.Core.IO.NuGet; 11 | using Cake.Core.Scripting; 12 | using Cake.Core.Scripting.Analysis; 13 | using Cake.Core.Packaging; 14 | using Cake.NuGet; 15 | using Cake.Host.Diagnostics; 16 | using Cake.Host.Scripting; 17 | using Cake.Host.Scripting.Mono; 18 | using Cake.Host.Scripting.Roslyn; 19 | using Cake.Host.Scripting.Roslyn.Nightly; 20 | using Cake.Host.Scripting.Roslyn.Stable; 21 | 22 | using LightInject; 23 | 24 | using Nancy; 25 | using Nancy.Authentication.Basic; 26 | using Nancy.Serialization.JsonNet; 27 | #endregion 28 | 29 | 30 | 31 | namespace CakeBoss.Host 32 | { 33 | public class HostRoot : ICompositionRoot 34 | { 35 | public void Compose(IServiceRegistry container) 36 | { 37 | //Core Services 38 | container.Register(new PerContainerLifetime()); 39 | container.Register(new PerContainerLifetime()); 40 | container.Register(new PerContainerLifetime()); 41 | container.Register(new PerContainerLifetime()); 42 | container.Register(new PerContainerLifetime()); 43 | container.Register(new PerContainerLifetime()); 44 | container.Register(new PerContainerLifetime()); 45 | container.Register(new PerContainerLifetime()); 46 | container.Register(new PerContainerLifetime()); 47 | 48 | container.Register(new PerContainerLifetime()); 49 | container.Register(new PerContainerLifetime()); 50 | container.Register(new PerContainerLifetime()); 51 | 52 | container.Register(new PerContainerLifetime()); 53 | 54 | container.Register(new PerContainerLifetime()); 55 | container.Register(new PerContainerLifetime()); 56 | 57 | 58 | 59 | // NuGet addins support 60 | container.Register(new PerContainerLifetime()); 61 | container.Register(new PerContainerLifetime()); 62 | 63 | container.Register(new PerContainerLifetime()); 64 | container.Register(new PerContainerLifetime()); 65 | container.Register(new PerContainerLifetime()); 66 | container.Register(new PerContainerLifetime()); 67 | 68 | // URI resource support. 69 | container.Register(new PerContainerLifetime()); 70 | container.Register(new PerContainerLifetime()); 71 | 72 | 73 | 74 | if (Type.GetType("Mono.Runtime") != null) 75 | { 76 | //Mono Scripting 77 | container.Register(new PerContainerLifetime()); 78 | } 79 | else 80 | { 81 | //Roslyn 82 | container.Register(new PerContainerLifetime()); 83 | container.Register(new PerContainerLifetime()); 84 | container.Register(new PerContainerLifetime()); 85 | } 86 | 87 | 88 | 89 | //Cake Services 90 | container.Register(new PerContainerLifetime()); 91 | container.Register(new PerContainerLifetime()); 92 | container.Register(new PerContainerLifetime()); 93 | container.Register(new PerContainerLifetime()); 94 | 95 | container.Register(new PerContainerLifetime()); 96 | container.Register(new PerContainerLifetime()); 97 | 98 | 99 | 100 | //Script Hosts 101 | container.Register(new PerContainerLifetime()); 102 | container.Register(new PerContainerLifetime()); 103 | container.Register(new PerContainerLifetime()); 104 | 105 | 106 | 107 | //Script Commands 108 | container.Register(new PerRequestLifeTime()); 109 | container.Register(new PerRequestLifeTime()); 110 | container.Register(new PerRequestLifeTime()); 111 | container.Register(new PerRequestLifeTime()); 112 | container.Register(new PerRequestLifeTime()); 113 | 114 | 115 | 116 | //CakeBoss Host 117 | container.Register(new PerContainerLifetime()); 118 | container.Register(new PerContainerLifetime()); 119 | 120 | 121 | 122 | //Nancy 123 | container.Register(); 124 | container.Register(); 125 | 126 | container.Register(new PerRequestLifeTime()); 127 | } 128 | } 129 | } -------------------------------------------------------------------------------- /src/Cake.Host/Scripting/Mono/CodeGen/Parsing/ScriptTokenizer.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Text; 3 | 4 | namespace Cake.Host.Scripting.Mono.CodeGen.Parsing 5 | { 6 | public sealed class ScriptTokenizer : IDisposable 7 | { 8 | private readonly ScriptBuffer _buffer; 9 | 10 | public ScriptTokenizer(string content) 11 | { 12 | _buffer = new ScriptBuffer(content); 13 | } 14 | 15 | public void Dispose() 16 | { 17 | _buffer.Dispose(); 18 | } 19 | 20 | public ScriptToken GetNextToken() 21 | { 22 | _buffer.EatWhiteSpace(); 23 | 24 | // Reached the end? 25 | if (_buffer.ReachedEnd) 26 | { 27 | return null; 28 | } 29 | 30 | // String? 31 | if (_buffer.CurrentToken == '\"') 32 | { 33 | return ParseString(); 34 | } 35 | 36 | // Word or Identifier? 37 | if (IsWordCharacter((char)_buffer.CurrentToken)) 38 | { 39 | return ParseWord(); 40 | } 41 | 42 | // Single line comment? 43 | if (_buffer.CurrentToken == '/' && _buffer.NextToken == '/') 44 | { 45 | return SkipSingleLineComment(); 46 | } 47 | 48 | // Multi line comment? 49 | if (_buffer.CurrentToken == '/' && _buffer.NextToken == '*') 50 | { 51 | return SkipMultiLineComment(); 52 | } 53 | 54 | // Some character. 55 | var tokenType = GetCharacterTokenType(); 56 | return new ScriptToken( 57 | tokenType, 58 | ((char)_buffer.CurrentToken).ToString(), 59 | _buffer.Position, 1); 60 | } 61 | 62 | private ScriptToken ParseString() 63 | { 64 | var start = _buffer.Position; 65 | 66 | var accumulator = new StringBuilder(); 67 | accumulator.Append((char)_buffer.CurrentToken); 68 | 69 | while (true) 70 | { 71 | if (!_buffer.Read()) 72 | { 73 | throw new InvalidOperationException("Unterminated string literal."); 74 | } 75 | 76 | accumulator.Append((char)_buffer.CurrentToken); 77 | 78 | var current = (char)_buffer.CurrentToken; 79 | if (current == '\"') 80 | { 81 | var last = (char)_buffer.PreviousToken; 82 | if (last != '\\') 83 | { 84 | break; 85 | } 86 | } 87 | } 88 | 89 | return new ScriptToken( 90 | ScriptTokenType.String, 91 | accumulator.ToString(), 92 | start, 93 | accumulator.Length); 94 | } 95 | 96 | private ScriptToken ParseWord() 97 | { 98 | var start = _buffer.Position; 99 | 100 | var accumulator = new StringBuilder(); 101 | accumulator.Append((char)_buffer.CurrentToken); 102 | 103 | while (true) 104 | { 105 | var current = _buffer.Peek(); 106 | if (current == -1 || !IsWordCharacter((char)current)) 107 | { 108 | break; 109 | } 110 | accumulator.Append((char)current); 111 | _buffer.Read(); // Nom nom nom 112 | } 113 | 114 | var type = ScriptTokenType.Word; 115 | 116 | var identity = accumulator.ToString(); 117 | if (identity.Equals("if", StringComparison.Ordinal)) 118 | { 119 | type = ScriptTokenType.If; 120 | } 121 | if (identity.Equals("else", StringComparison.Ordinal)) 122 | { 123 | type = ScriptTokenType.Else; 124 | } 125 | if (identity.Equals("while", StringComparison.Ordinal)) 126 | { 127 | type = ScriptTokenType.While; 128 | } 129 | if (identity.Equals("switch", StringComparison.Ordinal)) 130 | { 131 | type = ScriptTokenType.Switch; 132 | } 133 | 134 | return new ScriptToken( 135 | type, 136 | accumulator.ToString(), 137 | start, 138 | accumulator.Length); 139 | } 140 | 141 | private ScriptToken SkipSingleLineComment() 142 | { 143 | while (true) 144 | { 145 | if ((_buffer.CurrentToken == '\r' && _buffer.NextToken == '\n') || 146 | _buffer.CurrentToken == '\n') 147 | { 148 | break; 149 | } 150 | if (!_buffer.Read()) 151 | { 152 | break; 153 | } 154 | } 155 | return GetNextToken(); 156 | } 157 | 158 | private ScriptToken SkipMultiLineComment() 159 | { 160 | while (true) 161 | { 162 | if (_buffer.CurrentToken == '*' && _buffer.NextToken == '/') 163 | { 164 | _buffer.Read(); // Nom nom nom 165 | break; 166 | } 167 | if (!_buffer.Read()) 168 | { 169 | break; 170 | } 171 | } 172 | return GetNextToken(); 173 | } 174 | 175 | private ScriptTokenType GetCharacterTokenType() 176 | { 177 | switch (_buffer.CurrentToken) 178 | { 179 | case '{': return ScriptTokenType.LeftBrace; 180 | case '}': return ScriptTokenType.RightBrace; 181 | case '(': return ScriptTokenType.LeftParenthesis; 182 | case ')': return ScriptTokenType.RightParenthesis; 183 | case ';': return ScriptTokenType.Semicolon; 184 | } 185 | return ScriptTokenType.Character; 186 | } 187 | 188 | private static bool IsWordCharacter(char current) 189 | { 190 | return char.IsLetterOrDigit(current) || current == '_'; 191 | } 192 | } 193 | } --------------------------------------------------------------------------------