/// <summary> /// Registers a test task that depends on a sequence of pre-test tasks, test tasks and /// post-test tasks. /// </summary> /// <param name="envTasks">List of all plugin tasks for the current CI environment.</param> private void RegisterTestTask(IReadOnlyList <RegisteredTask> envTasks) { CakeTaskBuilder task = RegisterTask(TaskNames.Test) .Description("Runs tests in the project.") .IsDependentOn(TaskNames.Build); IEnumerable <RegisteredTask> preTestTasks = envTasks .Where(t => t.AttributeType == typeof(BeforePipelineTaskAttribute) && t.CoreTask == PipelineTask.Test); foreach (RegisteredTask preTestTask in preTestTasks) { task.IsDependentOn(preTestTask.Name); } IEnumerable <RegisteredTask> testTasks = envTasks .Where(t => t.AttributeType == typeof(PipelineTaskAttribute) && t.CoreTask == PipelineTask.Test); foreach (RegisteredTask testTask in testTasks) { task.IsDependentOn(testTask.Name); } IEnumerable <RegisteredTask> postTestTasks = envTasks .Where(t => t.AttributeType == typeof(AfterPipelineTaskAttribute) && t.CoreTask == PipelineTask.Test); foreach (RegisteredTask postTestTask in postTestTasks) { task.IsDependentOn(postTestTask.Name); } }
private void RegisterCicdTask(IReadOnlyList <RegisteredTask> envTasks) { CakeTaskBuilder task = RegisterTask(TaskNames.CiCd) .Description("Performs CI/CD (Build, test and deploy)") .IsDependentOn("CI"); IEnumerable <RegisteredTask> preDeployTasks = envTasks .Where(t => t.AttributeType == typeof(BeforePipelineTaskAttribute) && t.CoreTask == PipelineTask.Deploy); foreach (RegisteredTask preDeployTask in preDeployTasks) { task.IsDependentOn(preDeployTask.Name); } IEnumerable <RegisteredTask> deployTasks = envTasks .Where(t => t.AttributeType == typeof(PipelineTaskAttribute) && t.CoreTask == PipelineTask.Deploy); foreach (RegisteredTask deployTask in deployTasks) { task.IsDependentOn(deployTask.Name); } IEnumerable <RegisteredTask> postDeployTasks = envTasks .Where(t => t.AttributeType == typeof(AfterPipelineTaskAttribute) && t.CoreTask == PipelineTask.Deploy); foreach (RegisteredTask postDeployTask in postDeployTasks) { task.IsDependentOn(postDeployTask.Name); } }
private void RegisterIntegrationTestTask(IReadOnlyList <RegisteredTask> envTasks) { CakeTaskBuilder task = RegisterTask(TaskNames.IntegrationTest) .Description("Performs integration tests") .IsDependentOn("Build"); IEnumerable <RegisteredTask> preIntegrationTestTasks = envTasks .Where(t => t.AttributeType == typeof(BeforePipelineTaskAttribute) && t.CoreTask == PipelineTask.IntegrationTest); foreach (RegisteredTask preIntegrationTestTask in preIntegrationTestTasks) { task.IsDependentOn(preIntegrationTestTask.Name); } IEnumerable <RegisteredTask> integrationTestTasks = envTasks .Where(t => t.AttributeType == typeof(PipelineTaskAttribute) && t.CoreTask == PipelineTask.IntegrationTest); foreach (RegisteredTask integrationTestTask in integrationTestTasks) { task.IsDependentOn(integrationTestTask.Name); } IEnumerable <RegisteredTask> postIntegrationTestTasks = envTasks .Where(t => t.AttributeType == typeof(AfterPipelineTaskAttribute) && t.CoreTask == PipelineTask.IntegrationTest); foreach (RegisteredTask postIntegrationTestTask in postIntegrationTestTasks) { task.IsDependentOn(postIntegrationTestTask.Name); } }
/// <summary> /// Registers a build task that depends on a sequence of pre-build tasks, build tasks and /// post-build tasks. /// </summary> /// <param name="envTasks">List of all plugin tasks for the current CI environment.</param> private void RegisterBuildTask(IReadOnlyList <RegisteredTask> envTasks) { CakeTaskBuilder task = RegisterTask(TaskNames.Build) .Description("Builds the solution.") .IsDependentOn(TaskNames.Config); // Add pre-build tasks. IEnumerable <RegisteredTask> preBuildTasks = envTasks .Where(t => t.AttributeType == typeof(BeforePipelineTaskAttribute) && t.CoreTask == PipelineTask.Build); foreach (RegisteredTask preBuildTask in preBuildTasks) { task.IsDependentOn(preBuildTask.Name); } // Add build tasks. IEnumerable <RegisteredTask> buildTasks = envTasks .Where(t => t.AttributeType == typeof(PipelineTaskAttribute) && t.CoreTask == PipelineTask.Build); foreach (RegisteredTask buildTask in buildTasks) { task.IsDependentOn(buildTask.Name); } // Add post-build tasks. IEnumerable <RegisteredTask> postBuildTasks = envTasks .Where(t => t.AttributeType == typeof(AfterPipelineTaskAttribute) && t.CoreTask == PipelineTask.Build); foreach (RegisteredTask postBuildTask in postBuildTasks) { task.IsDependentOn(postBuildTask.Name); } }
/// <summary> /// Registers a task that performs final setup of configuration after all plugin-specific /// config tasks have been run. /// <para/> /// This includes: /// 1. Runs all configuration lambdas from the <c>ConfigureTask</c> methods in the /// build.cake file. /// 2. Override configurations with any matching values from the environment. /// 3. Override configurations with any matching values from the command line. /// </summary> /// <param name="envTasks">List of all plugin tasks for the current CI environment.</param> private void RegisterConfigTask(IReadOnlyList <RegisteredTask> envTasks) { CakeTaskBuilder task = RegisterTask(TaskNames.Config) .Description("Finalizes configurations and displays final configuration values."); // Create dependency on all plugin configuration tasks. IEnumerable <RegisteredTask> configTasks = envTasks .Where(t => t.AttributeType == typeof(ConfigAttribute)) .OrderBy(t => t.Order); foreach (RegisteredTask configTask in configTasks) { task.IsDependentOn(configTask.Name); } task.Does(ctx => { TaskConfig config = TaskConfig.Current; // Run configurations specified in the build.cake file config.PerformDeferredSetup(); // Override configurations from environment variables IDictionary <string, string> envVars = ctx.Environment.GetEnvironmentVariables(); foreach (KeyValuePair <string, string> envVar in envVars) { if (config.Data.ContainsKey(envVar.Key)) { config.Data[envVar.Key] = envVar.Value; } } // Override configurations from command line arguments var keys = config.Data.Keys.ToList(); foreach (string key in keys) { if (ctx.Arguments.HasArgument(key)) { config.Data[key] = ctx.Arguments.GetArgument(key); } } // Display the final configuration values ctx.LogHighlight("Final Configurations"); ctx.LogHighlight("--------------------"); foreach (KeyValuePair <string, object> data in config.Data.OrderBy(kvp => kvp.Key)) { ctx.LogHighlight($"{data.Key} = {data.Value?.Dump() ?? "[NULL]"}"); } EnvConfig env = config.Load <EnvConfig>(); // Clean out output directories or create them //TODO: Can these directories be created on-demand? For some project types like Angular, //these folders are ignored and the dist folder is used. ctx.EnsureDirectoryExists(env.Directories.Artifacts); ctx.EnsureDirectoryExists(env.Directories.BinaryOutput); ctx.EnsureDirectoryExists(env.Directories.TestOutput); }); }
public void Should_Add_Dependency_To_Task() { // Given var task = new CakeTask("task"); var builder = new CakeTaskBuilder(task); // When builder.IsDependentOn("other"); // Then Assert.Single(task.Dependencies); }
public void Should_Add_Dependency_To_Task() { // Given var task = new ActionTask("task"); var builder = new CakeTaskBuilder <ActionTask>(task); // When builder.IsDependentOn("other"); // Then Assert.Equal(1, task.Dependencies.Count); }
public void Should_Throw_If_OtherBuilder_Is_Null() { // Given var parentTask = new ActionTask("parent"); var builder = new CakeTaskBuilder <ActionTask>(parentTask); CakeTaskBuilder <ActionTask> childTaskBuilder = null; // When var result = Record.Exception(() => builder.IsDependentOn(childTaskBuilder)); // Then Assert.IsArgumentNullException(result, "other"); }
public void Should_Throw_If_Builder_Is_Null() { // Given var childTask = new ActionTask("child"); CakeTaskBuilder <ActionTask> builder = null; var childTaskBuilder = new CakeTaskBuilder <ActionTask>(childTask); // When var result = Record.Exception(() => builder.IsDependentOn(childTaskBuilder)); // Then AssertEx.IsArgumentNullException(result, "builder"); }
public void Should_Add_Dependency_To_Task_With_Correct_Name() { // Given var parentTask = new ActionTask("parent"); var childTask = new ActionTask("child"); var builder = new CakeTaskBuilder <ActionTask>(parentTask); var childTaskBuilder = new CakeTaskBuilder <ActionTask>(childTask); // When builder.IsDependentOn(childTaskBuilder); // Then Assert.Equal(parentTask.Dependencies[0], childTaskBuilder.Task.Name); }
public void Should_Add_Dependency_To_Task() { // Given var parentTask = new ActionTask("parent"); var childTask = new ActionTask("child"); var builder = new CakeTaskBuilder <ActionTask>(parentTask); var cakeTaskBuilder = new CakeTaskBuilder <ActionTask>(childTask); // When builder.IsDependentOn(cakeTaskBuilder); // Then Assert.Equal(1, parentTask.Dependencies.Count); }
public void Should_Add_Dependency_To_Task() { // Given var parentTask = new CakeTask("parent"); var childTask = new CakeTask("child"); var builder = new CakeTaskBuilder(parentTask); var cakeTaskBuilder = new CakeTaskBuilder(childTask); // When builder.IsDependentOn(cakeTaskBuilder); // Then Assert.Single(parentTask.Dependencies); }
/// <summary> /// Creates an actual Cake task from the internal <see cref="RegisteredTask"/> structure. /// </summary> private void RegisterPluginTasks() { foreach (RegisteredTask registeredTask in _registeredTasks) { CakeTaskBuilder builder = RegisterTask(registeredTask.Name) .Description(registeredTask.Description); if (registeredTask.ContinueOnError) { builder.ContinueOnError(); } if (registeredTask.AttributeType == typeof(TaskAttribute) && registeredTask.RequiresConfig) { builder.IsDependentOn(TaskNames.Config); } ParameterInfo[] parameters = registeredTask.Method.GetParameters(); switch (parameters.Length) { case 2: var action2 = (Action <ICakeContext, TaskConfig>)registeredTask.Method.CreateDelegate( typeof(Action <ICakeContext, TaskConfig>)); builder.Does(action2); break; case 1: if (parameters[0].ParameterType == typeof(TaskConfig)) { Action <ICakeContext, TaskConfig> action1 = (_, cfg) => { registeredTask.Method.Invoke(obj: null, new object[] { cfg }); }; builder.Does(action1); } else { var action1 = (Action <ICakeContext>)registeredTask.Method.CreateDelegate(typeof(Action <ICakeContext>)); builder.Does(action1); } break; default: var action = (Action)registeredTask.Method.CreateDelegate(typeof(Action)); builder.Does(action); break; } } }
private void GenerateTasks(string taskName, IEnumerable <Target> targets) { CakeTaskBuilder <ActionTask> buildTask = _parameters.Context.Task($"build-{taskName}"); CakeTaskBuilder <ActionTask> releaseTask = _parameters.Context.Task($"release-{taskName}"); CakeTaskBuilder <ActionTask> deployTask = _parameters.Context.Task($"deploy-{taskName}"); foreach (Target target in targets) { buildTask.IsDependentOn(target.BuildTaskName); releaseTask.IsDependentOn(target.ReleaseTaskName); deployTask.IsDependentOn(target.DeployTaskName); } buildTask.Does(() => { }); releaseTask.Does(() => { }); deployTask.Does(() => { }); }
/// <summary> /// Adds dependency between tasks /// </summary> /// <param name="helper">TaskHelper</param> /// <param name="task">Task</param> /// <param name="dependentTaskName">Task name</param> public static void AddTaskDependency( this IHelperTaskHandler helper, CakeTaskBuilder <ActionTask> task, string dependentTaskName) { if (task == null) { throw new ArgumentNullException(nameof(task)); } if (string.IsNullOrWhiteSpace(dependentTaskName)) { throw new ArgumentNullException(nameof(dependentTaskName)); } if (task.Task.Dependencies.Any(t => t == dependentTaskName)) { return; } task.IsDependentOn(dependentTaskName); }
public void Build() { List <Target> targets = MergeTargets(_parameters); //generate application-target-platform foreach (Target target in targets) { //generate application-target-platform _parameters.Context.Task(target.BuildTaskName).Does(() => { foreach (IStep preBuild in target.Configuration.StepsOf <PreBuildStepAttribute>()) { preBuild.Execute(target.Configuration, StepType.PreBuild); } foreach (IStep build in target.Configuration.StepsOf <BuildStepAttribute>()) { build.Execute(target.Configuration, StepType.Build); } foreach (IStep postBuild in target.Configuration.StepsOf <PostBuildStepAttribute>()) { postBuild.Execute(target.Configuration, StepType.PostBuild); } }); _parameters.Context.Task(target.ReleaseTaskName) .IsDependentOn(CleanTaskBuilder.TASK_NAME) .IsDependentOn(target.BuildTaskName) .Does(() => { foreach (IStep preRelease in target.Configuration.StepsOf <PreReleaseStepAttribute>()) { preRelease.Execute(target.Configuration, StepType.PreRelease); } foreach (IStep release in target.Configuration.StepsOf <ReleaseStepAttribute>()) { release.Execute(target.Configuration, StepType.Release); } foreach (IStep postRelease in target.Configuration.StepsOf <PostReleaseStepAttribute>()) { postRelease.Execute(target.Configuration, StepType.PostRelease); } }); _parameters.Context.Task(target.DeployTaskName) .IsDependentOn(CleanTaskBuilder.TASK_NAME) .IsDependentOn(target.ReleaseTaskName) .Does(() => { foreach (IStep preDeploy in target.Configuration.StepsOf <PreDeployStepAttribute>()) { preDeploy.Execute(target.Configuration, StepType.PreDeploy); } foreach (IStep deploy in target.Configuration.StepsOf <DeployStepAttribute>()) { deploy.Execute(target.Configuration, StepType.Deploy); } foreach (IStep postDeploy in target.Configuration.StepsOf <PostDeployStepAttribute>()) { postDeploy.Execute(target.Configuration, StepType.PostDeploy); } }); } //generate application-target foreach (IList <Target> grouping in targets.GroupBy(x => x.ApplicationName).SelectMany(x => x.GroupBy(y => y.TargetName).Select(y => y.ToList()))) { Target sample = grouping.First(); GenerateTasks($"{sample.ApplicationName}-{sample.TargetName}", grouping); } //generate application-platform foreach (IList <Target> grouping in targets.GroupBy(x => x.ApplicationName).SelectMany(x => x.GroupBy(y => y.PlatformName).Select(y => y.ToList()))) { Target sample = grouping.First(); GenerateTasks($"{sample.ApplicationName}-{sample.PlatformName}", grouping); } //generate target-platform foreach (IList <Target> grouping in targets.GroupBy(x => x.TargetName).SelectMany(x => x.GroupBy(y => y.PlatformName).Select(y => y.ToList()))) { Target sample = grouping.First(); GenerateTasks($"{sample.TargetName}-{sample.PlatformName}", grouping); } //generate application foreach (IList <Target> grouping in targets.GroupBy(x => x.ApplicationName).Select(y => y.ToList())) { Target sample = grouping.First(); GenerateTasks($"{sample.ApplicationName}", grouping); } //generate target foreach (IList <Target> grouping in targets.GroupBy(x => x.TargetName).Select(y => y.ToList())) { Target sample = grouping.First(); GenerateTasks($"{sample.TargetName}", grouping); } //generate platform foreach (IList <Target> grouping in targets.GroupBy(x => x.PlatformName).Select(y => y.ToList())) { Target sample = grouping.First(); GenerateTasks($"{sample.PlatformName}", grouping); } CakeTaskBuilder <ActionTask> buildTask = _parameters.Context.Task("build"); CakeTaskBuilder <ActionTask> releaseTask = _parameters.Context.Task("release"); CakeTaskBuilder <ActionTask> deployTask = _parameters.Context.Task("deploy"); foreach (Target target in targets) { buildTask.IsDependentOn(target.BuildTaskName); releaseTask.IsDependentOn(target.ReleaseTaskName); deployTask.IsDependentOn(target.DeployTaskName); } buildTask.Does(() => { }); releaseTask.Does(() => { }); deployTask.Does(() => { }); }
/// <summary> /// Configures the dependency, criteria and error handling for a dotnet-lib recipe task /// </summary> /// <param name="builder">Cake task builder</param> /// <param name="lib"><see cref="DotNetLib"/> recipe configuration</param> /// <param name="dependentOn">Dependent task name</param> /// <param name="dependee">Dependee task name</param> /// <returns></returns> public static CakeTaskBuilder ConfigTaskFor( this CakeTaskBuilder builder, DotNetLib lib, string dependentOn, string dependee = null) { // Bump dependent task forward based on recipe config if (dependentOn == lib.Tasks.Names.Commit && !lib.UseCommitTask) { dependentOn = lib.Tasks.Names.Package; } if (dependentOn == lib.Tasks.Names.PostBuild && !lib.UsePostBuildTask) { dependentOn = lib.Tasks.Names.Build; } if (dependentOn == lib.Tasks.Names.PreBuild && !lib.UsePreBuildTask) { dependentOn = lib.Tasks.Names.Clean; } if (dependentOn == lib.Tasks.Names.AssemblyInfo && !lib.UpdateAssemblyInfo) { dependentOn = lib.Tasks.Names.ReleaseNotes; } if (dependentOn == lib.Tasks.Names.ReleaseNotes && !lib.PrepareReleaseNotes) { dependentOn = lib.Tasks.Names.Version; } builder .IsDependentOn(dependentOn) .WithCriteria(() => !lib.SkipRemainingTasks && !lib.Errored) .OnError(ex => lib.SetError(builder, ex)); // Bump dependee back based on lib config if (!string.IsNullOrEmpty(dependee)) { if (dependee == lib.Tasks.Names.ReleaseNotes && !lib.PrepareReleaseNotes) { dependee = lib.Tasks.Names.AssemblyInfo; } if (dependee == lib.Tasks.Names.AssemblyInfo && !lib.UpdateAssemblyInfo) { dependee = lib.Tasks.Names.Clean; } if (dependee == lib.Tasks.Names.PreBuild && !lib.UsePreBuildTask) { dependee = lib.Tasks.Names.Build; } if (dependee == lib.Tasks.Names.PostBuild && !lib.UsePostBuildTask) { dependee = lib.Tasks.Names.Test; } if (dependee == lib.Tasks.Names.Commit && !lib.UseCommitTask) { dependee = lib.Tasks.Names.Push; } builder.IsDependeeOf(dependee); } return(builder); }
/// <summary> /// Registers built-in utility tasks that can be used to display various details about the /// Cake tasks, such as listing environments, tasks and configurations. /// </summary> private void RegisterBuiltInTasks() { // The Default task lists all available public tasks (tasks not prefixed with underscore). void RegisterDefaultTask() { RegisterTask("Default") .Does(ctx => { ctx.Log.Information("Task List"); ctx.Log.Information("---------"); foreach (ICakeTaskInfo task in Tasks) { if (task.Name.StartsWith("_")) { continue; } if (task.Name.Equals("Default", StringComparison.OrdinalIgnoreCase)) { continue; } ctx.Log.Information(task.Name); if (!string.IsNullOrWhiteSpace(task.Description)) { ctx.Log.Information($" {task.Description}"); } } }); } // The ListEnvs task goes through all available tasks and identifies all the available // environments. void RegisterListEnvsTask() { RegisterTask(TaskNames.ListEnvs) .Description("Lists all available environments.") .Does(ctx => { IList <string> environments = _registeredTasks .Select(task => task.CiSystem) .Distinct(StringComparer.OrdinalIgnoreCase) .OrderBy(env => env) .ToList(); if (environments.Count > 0) { ctx.Log.Information("Available Environments"); ctx.Log.Information("----------------------"); foreach (string env in environments) { ctx.Log.Information(env); } } else { ctx.Log.Information("No environments found!"); } }); } // The ListConfigs task lists the final values of all configuration values. It depends on // the _Config task, as it needs to execute all the config tasks first, before it can get // the final vakues. void RegisterListConfigsTask() { CakeTaskBuilder listConfigsTask = RegisterTask(TaskNames.ListConfigs) .Description("Lists all available configurations."); IEnumerable <RegisteredTask> configTasks = GetTasksForCiEnvironment() .Where(rt => rt.AttributeType == typeof(ConfigAttribute)); foreach (RegisteredTask configTask in configTasks) { listConfigsTask = listConfigsTask.IsDependentOn(configTask.Name); } listConfigsTask.IsDependentOn(TaskNames.Config); } // The ListTasks tasks lists all tasks including private tasks (which are prefixed with an // underscore). void RegisterListTasksTask() { RegisterTask(TaskNames.ListTasks) .Description("Lists all tasks including private tasks.") .Does(ctx => { ctx.Log.Information("Task List"); ctx.Log.Information("---------"); foreach (ICakeTaskInfo task in Tasks) { if (task.Name.Equals("Default", StringComparison.OrdinalIgnoreCase)) { continue; } ctx.Log.Information(task.Name); if (!string.IsNullOrWhiteSpace(task.Description)) { ctx.Log.Information($" {task.Description}"); } } }); } RegisterDefaultTask(); RegisterListEnvsTask(); RegisterListConfigsTask(); RegisterListTasksTask(); }