コード例 #1
0
        /// <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);
            }
        }
コード例 #2
0
        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);
            }
        }
コード例 #3
0
        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);
            }
        }
コード例 #4
0
        /// <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);
            }
        }
コード例 #5
0
        /// <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);
            });
        }
コード例 #6
0
            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);
            }
コード例 #7
0
            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);
            }
コード例 #8
0
            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");
            }
コード例 #9
0
            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");
            }
コード例 #10
0
            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);
            }
コード例 #11
0
            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);
            }
コード例 #12
0
                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);
                }
コード例 #13
0
        /// <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;
                }
            }
        }
コード例 #14
0
        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(() => { });
        }
コード例 #15
0
        /// <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);
        }
コード例 #16
0
        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(() => { });
        }
コード例 #17
0
        /// <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);
        }
コード例 #18
0
        /// <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();
        }