Skip to content

Commit

Permalink
Fix issues when build has no default target defined
Browse files Browse the repository at this point in the history
  • Loading branch information
matkoch committed Apr 25, 2019
1 parent 3853943 commit be7d821
Show file tree
Hide file tree
Showing 15 changed files with 105 additions and 52 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ namespace Nuke.Common.Execution
{
public interface IBuildExtension
{
void Execute(NukeBuild build, IReadOnlyCollection<ExecutableTarget> executableTargets);
void Execute(NukeBuild build, IReadOnlyCollection<ExecutableTarget> executableTargets, IReadOnlyCollection<ExecutableTarget> executionPlan);
}

public interface IPreLogoBuildExtension : IBuildExtension
Expand Down
3 changes: 2 additions & 1 deletion source/Nuke.Common/Execution/BuildManager.cs
Original file line number Diff line number Diff line change
Expand Up @@ -60,11 +60,12 @@ public static int Execute<T>(Expression<Func<T, Target>> defaultTargetExpression
Logger.Info($"NUKE Execution Engine {typeof(BuildManager).Assembly.GetInformationalText()}");
Logger.Normal();

build.ExecuteExtensions<IPostLogoBuildExtension>();
build.ExecutionPlan = ExecutionPlanner.GetExecutionPlan(
build.ExecutableTargets,
ParameterService.Instance.GetParameter<string[]>(() => build.InvokedTargets) ??
ParameterService.Instance.GetPositionalCommandLineArguments<string>(separator: Constants.TargetsSeparator.Single()));

build.ExecuteExtensions<IPostLogoBuildExtension>();
CancellationHandler += Finish;

InjectionUtility.InjectValues(build, x => !x.IsFast);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,10 @@ public class CheckBuildProjectConfigurationsAttribute : Attribute, IPostLogoBuil
{
public int TimeoutInMilliseconds { get; set; } = 500;

public void Execute(NukeBuild build, IReadOnlyCollection<ExecutableTarget> executableTargets)
public void Execute(
NukeBuild build,
IReadOnlyCollection<ExecutableTarget> executableTargets,
IReadOnlyCollection<ExecutableTarget> executionPlan)
{
ControlFlow.AssertWarn(Task.Run(CheckConfiguration).Wait(TimeoutInMilliseconds),
$"Could not complete checking build configurations within {TimeoutInMilliseconds} milliseconds.");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,10 @@ namespace Nuke.Common.Execution
[AttributeUsage(AttributeTargets.Class)]
public class CheckPathEnvironmentVariableAttribute : Attribute, IPostLogoBuildExtension
{
public void Execute(NukeBuild build, IReadOnlyCollection<ExecutableTarget> executableTargets)
public void Execute(
NukeBuild build,
IReadOnlyCollection<ExecutableTarget> executableTargets,
IReadOnlyCollection<ExecutableTarget> executionPlan)
{
ProcessTasks.CheckPathEnvironmentVariable();
}
Expand Down
5 changes: 4 additions & 1 deletion source/Nuke.Common/Execution/ExecutionPlanHtmlService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,10 @@ private static string GetEvents(IReadOnlyCollection<ExecutableTarget> executable
var builder = new StringBuilder();

// When not hovering anything, highlight the default plan
var defaultPlan = ExecutionPlanner.GetExecutionPlan(executableTargets, new[] { executableTargets.Single(x => x.IsDefault).Name });
var defaultTarget = executableTargets.SingleOrDefault(x => x.IsDefault);
var defaultPlan = defaultTarget != null
? ExecutionPlanner.GetExecutionPlan(executableTargets, new[] { defaultTarget?.Name })
: new ExecutableTarget[0];
defaultPlan.ForEach(x => builder.AppendLine($@" $(""#{x.Name}"").addClass('highlight');"));

foreach (var executableTarget in executableTargets)
Expand Down
21 changes: 13 additions & 8 deletions source/Nuke.Common/Execution/ExecutionPlanner.cs
Original file line number Diff line number Diff line change
Expand Up @@ -51,21 +51,23 @@ private static IReadOnlyCollection<ExecutableTarget> GetExecutionPlanInternal(
var cycles = scc.DetectCycle(graphAsList).Cycles().ToList();
if (cycles.Count > 0)
{
ControlFlow.Fail(
Logger.Error(
new[] { "Circular dependencies between targets:" }
.Concat(cycles.Select(x => $" - {x.Select(y => y.Value.Name).JoinComma()}"))
.JoinNewLine());
Environment.Exit(exitCode: -1);
}

while (graphAsList.Any())
{
var independents = graphAsList.Where(x => !graphAsList.Any(y => y.Dependencies.Contains(x))).ToList();
if (EnvironmentInfo.ArgumentSwitch("strict") && independents.Count > 1)
{
ControlFlow.Fail(
new[] { "Incomplete target definition order." }
Logger.Error(
new[]{"Incomplete target definition order."}
.Concat(independents.Select(x => $" - {x.Value.Name}"))
.JoinNewLine());
Environment.Exit(exitCode: -1);
}

var independent = independents.First();
Expand Down Expand Up @@ -100,18 +102,21 @@ private static ExecutableTarget GetExecutableTarget(
{
var executableTarget = executableTargets.SingleOrDefault(x => x.Name.EqualsOrdinalIgnoreCase(targetName));
if (executableTarget == null)
ControlFlow.Fail($"Target with name '{targetName}' is not available.");
{
Logger.Error(
new[] { $"Target with name '{targetName}' does not exist. Available targets are:" }
.Concat(executableTargets.Select(x => $" - {x.Name}").OrderBy(x => x))
.JoinNewLine());
Environment.Exit(exitCode: -1);
}

return executableTarget;
}

private static ExecutableTarget[] GetDefaultTarget(IReadOnlyCollection<ExecutableTarget> executableTargets)
{
var target = executableTargets.SingleOrDefault(x => x.IsDefault);
if (target == null)
Fail("No target has been marked to be the default.", executableTargets);

return new[] { target };
return target != null ? new[] { target } : new ExecutableTarget[0];
}

private static void Fail(string message, IReadOnlyCollection<ExecutableTarget> executableTargets)
Expand Down
28 changes: 28 additions & 0 deletions source/Nuke.Common/Execution/HandleHelpRequestAttribute.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
// Copyright 2019 Maintainers of NUKE.
// Distributed under the MIT License.
// https://github.com/nuke-build/nuke/blob/master/LICENSE

using System;
using System.Collections.Generic;
using System.Linq;

namespace Nuke.Common.Execution
{
[AttributeUsage(AttributeTargets.Class)]
internal class HandleHelpRequestAttribute : Attribute, IPostLogoBuildExtension
{
public void Execute(
NukeBuild build,
IReadOnlyCollection<ExecutableTarget> executableTargets,
IReadOnlyCollection<ExecutableTarget> executionPlan)
{
if (!NukeBuild.Help && executionPlan.Count > 0)
return;

Logger.Normal(HelpTextService.GetTargetsText(build.ExecutableTargets));
Logger.Normal(HelpTextService.GetParametersText(build));

Environment.Exit(exitCode: 0);
}
}
}
29 changes: 0 additions & 29 deletions source/Nuke.Common/Execution/HandleHelpRequestsAttribute.cs

This file was deleted.

26 changes: 26 additions & 0 deletions source/Nuke.Common/Execution/HandlePlanRequestAttribute.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
// Copyright 2019 Maintainers of NUKE.
// Distributed under the MIT License.
// https://github.com/nuke-build/nuke/blob/master/LICENSE

using System;
using System.Collections.Generic;
using System.Linq;

namespace Nuke.Common.Execution
{
[AttributeUsage(AttributeTargets.Class)]
internal class HandlePlanRequestAttribute : Attribute, IPostLogoBuildExtension
{
public void Execute(
NukeBuild build,
IReadOnlyCollection<ExecutableTarget> executableTargets,
IReadOnlyCollection<ExecutableTarget> executionPlan)
{
if (!NukeBuild.Plan)
return;

ExecutionPlanHtmlService.ShowPlan(build.ExecutableTargets);
Environment.Exit(exitCode: 0);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,10 @@ namespace Nuke.Common.Execution
[AttributeUsage(AttributeTargets.Class)]
internal class HandleShellCompletionAttribute : Attribute, IPreLogoBuildExtension
{
public void Execute(NukeBuild build, IReadOnlyCollection<ExecutableTarget> executableTargets)
public void Execute(
NukeBuild build,
IReadOnlyCollection<ExecutableTarget> executableTargets,
IReadOnlyCollection<ExecutableTarget> executionPlan)
{
var completionItems = new SortedDictionary<string, string[]>();

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,10 @@ public class HandleVisualStudioDebuggingAttribute : Attribute, IPreLogoBuildExte
{
public int TimeoutInMilliseconds { get; } = 10_000;

public void Execute(NukeBuild build, IReadOnlyCollection<ExecutableTarget> executableTargets)
public void Execute(
NukeBuild build,
IReadOnlyCollection<ExecutableTarget> executableTargets,
IReadOnlyCollection<ExecutableTarget> executionPlan)
{
if (!ParameterService.Instance.GetParameter<bool>(Constants.VisualStudioDebugParameterName))
return;
Expand Down
4 changes: 2 additions & 2 deletions source/Nuke.Common/Execution/HelpTextService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ public static string GetTargetsText(IReadOnlyCollection<ExecutableTarget> execut

public static string GetParametersText(NukeBuild build)
{
var defaultTarget = build.ExecutableTargets.Single(x => x.IsDefault);
var defaultTarget = build.ExecutableTargets.SingleOrDefault(x => x.IsDefault);
var builder = new StringBuilder();

var parameters = InjectionUtility.GetParameterMembers(build.GetType())
Expand All @@ -50,7 +50,7 @@ void PrintParameter(MemberInfo parameter)
var description = SplitLines(
// TODO: remove
ParameterService.Instance.GetParameterDescription(parameter)
?.Replace("{default_target}", defaultTarget.Name).Append(".")
?.Replace("{default_target}", defaultTarget?.Name).Append(".")
?? "<no description>");
var parameterName = ParameterService.Instance.GetParameterName(parameter).SplitCamelHumpsWithSeparator("-");
builder.AppendLine($" --{parameterName.PadRight(padRightParameter)} {description.First()}");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,10 @@ namespace Nuke.Common.Execution
[AttributeUsage(AttributeTargets.Class)]
public class UnsetVisualStudioEnvironmentVariablesAttribute : Attribute, IPreLogoBuildExtension
{
public void Execute(NukeBuild build, IReadOnlyCollection<ExecutableTarget> executableTargets)
public void Execute(
NukeBuild build,
IReadOnlyCollection<ExecutableTarget> executableTargets,
IReadOnlyCollection<ExecutableTarget> executionPlan)
{
new[]
{
Expand Down
9 changes: 5 additions & 4 deletions source/Nuke.Common/NukeBuild.cs
Original file line number Diff line number Diff line change
Expand Up @@ -28,13 +28,13 @@ namespace Nuke.Common
/// class DefaultBuild : NukeBuild
/// {
/// public static int Main () => Execute&lt;DefaultBuild&gt;(x => x.Compile);
///
///
/// Target Clean =&gt; _ =&gt; _
/// .Executes(() =&gt;
/// {
/// EnsureCleanDirectory(OutputDirectory);
/// });
///
///
/// Target Compile =&gt; _ =&gt; _
/// .DependsOn(Clean)
/// .Executes(() =&gt;
Expand All @@ -45,7 +45,8 @@ namespace Nuke.Common
/// </code>
/// </example>
[PublicAPI]
[HandleHelpRequests]
[HandleHelpRequest]
[HandlePlanRequest]
[HandleShellCompletion]
[HandleVisualStudioDebugging]
public abstract partial class NukeBuild
Expand Down Expand Up @@ -87,7 +88,7 @@ protected static int Execute<T>(Expression<Func<T, Target>> defaultTargetExpress
internal void ExecuteExtensions<T>()
where T : IBuildExtension
{
GetType().GetCustomAttributes().OfType<T>().ForEach(x => x.Execute(this, ExecutableTargets));
GetType().GetCustomAttributes().OfType<T>().ForEach(x => x.Execute(this, ExecutableTargets, ExecutionPlan));
}

protected internal virtual IOutputSink OutputSink
Expand Down
5 changes: 4 additions & 1 deletion source/Nuke.Common/Tooling/VerbosityMappingAttribute.cs
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,10 @@ public VerbosityMappingAttribute(Type targetType)
public string Normal { get; set; }
public string Verbose { get; set; }

public void Execute(NukeBuild build, IReadOnlyCollection<ExecutableTarget> executableTargets)
public void Execute(
NukeBuild build,
IReadOnlyCollection<ExecutableTarget> executableTargets,
IReadOnlyCollection<ExecutableTarget> executionPlan)
{
object GetMappedValue(string name)
=> _targetType
Expand Down

0 comments on commit be7d821

Please sign in to comment.