Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -142,7 +142,7 @@ private static async Task<int> ExecuteAsync(
}
}

activity.Fail(errorTree);
await activity.FailAllAsync(errorTree);

throw new ExitException("Client publish failed.");

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -124,7 +124,7 @@ private static async Task<int> ExecuteAsync(
}
}

activity.Fail(errorTree);
await activity.FailAllAsync(errorTree);

throw new ExitException("Client validation failed.");

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -144,7 +144,7 @@ async Task<int> PublishFusionConfigurationWithArchiveAsync()
throw new ExitException(Messages.ArchiveFileDoesNotExist(archiveFile));
}

await using var activity = StartPublishActivity(console, stageName, apiId, force);
await using var activity = StartPublishActivity(console, stageName, apiId, tag, force);
await using var archiveStream = fileSystem.OpenReadStream(archiveFile);

return await ExecutePublishAsync(
Expand All @@ -170,7 +170,7 @@ async Task<int> PublishFusionConfigurationWithSourceSchemaFilesAsync()
}
}

await using var activity = StartPublishActivity(console, stageName, apiId, force);
await using var activity = StartPublishActivity(console, stageName, apiId, tag, force);

var newSourceSchemas = await FusionComposeCommand.ReadSourceSchemasAsync(
fileSystem,
Expand All @@ -189,7 +189,7 @@ async Task<int> PublishFusionConfigurationWithSourceSchemasAsync()
.Select(i => ParseSourceSchemaVersion(i, tag))
.ToArray();

await using var activity = StartPublishActivity(console, stageName, apiId, force);
await using var activity = StartPublishActivity(console, stageName, apiId, tag, force);

var newSourceSchemas = new Dictionary<string, (SourceSchemaText, JsonDocument)>();

Expand Down Expand Up @@ -371,7 +371,11 @@ await FusionPublishHelpers.ClaimDeploymentSlotAsync(
}
else if (!force)
{
throw new ExitException("Failed to validate configuration.");
// Write directly instead of throwing so the release-slot fallback
// in the outer catch is not triggered — the publish hasn't actually
// reserved any remote state that needs tearing down here.
console.Error.WriteErrorLine("Fusion configuration validation failed.");
return ExitCodes.Error;
}
}

Expand Down Expand Up @@ -477,11 +481,12 @@ private static INitroConsoleActivity StartPublishActivity(
INitroConsole console,
string stageName,
string apiId,
string tag,
bool force)
{
var activity = console.StartActivity(
$"Publishing Fusion configuration to stage '{stageName}' of API '{apiId.EscapeMarkup()}'",
"Failed to publish Fusion configuration.");
$"Publishing new Fusion configuration version '{tag.EscapeMarkup()}' of API '{apiId.EscapeMarkup()}' to stage '{stageName.EscapeMarkup()}'",
"Failed to publish a new Fusion configuration version.");

if (force)
{
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
using System.Text.Json;
using ChilliCream.Nitro.Client;
using ChilliCream.Nitro.Client.FusionConfiguration;
using ChilliCream.Nitro.CommandLine.Helpers;
using HotChocolate.Fusion;
using HotChocolate.Fusion.Logging;
using HotChocolate.Fusion.Packaging;
Expand Down Expand Up @@ -68,7 +69,7 @@ public static async Task<string> RequestDeploymentSlotAsync(
throw MutationReturnedNoData();
}

// activity.Update($"Request ID: {requestId.EscapeMarkup()}");
activity.Update($"Publication request created. {$"(ID: {requestId.EscapeMarkup()})".Dim()}");

using var subscriptionCancellation =
CancellationTokenSource.CreateLinkedTokenSource(cancellationToken);
Expand Down Expand Up @@ -103,8 +104,9 @@ public static async Task<string> RequestDeploymentSlotAsync(
}
}

activity.Fail(errorTree);
throw Exit("Your request has failed.");
await activity.FailAllAsync(errorTree);

throw new ExitException("Your request has failed.");

case IFusionConfigurationPublishingSuccess:
await subscriptionCancellation.CancelAsync();
Expand Down Expand Up @@ -225,7 +227,7 @@ public static async Task<bool> UploadFusionConfigurationAsync(
}
}

activity.Fail(publishErrorTree);
await activity.FailAllAsync(publishErrorTree);
throw new ExitException("Failed to publish the new configuration.");

case IFusionConfigurationPublishingSuccess:
Expand Down Expand Up @@ -336,17 +338,17 @@ public static async Task<bool> ValidateFusionConfigurationAsync(
{
case IProcessingTaskIsQueued:
throw Exit(
"Your request is in the queued state. Try to run `fusion-configuration publish start` once the request is ready ");
"Your request is in the queued state. Try to run `fusion-configuration publish start` once the request is ready.");

case IFusionConfigurationPublishingFailed:
throw Exit("Your request has already failed");
throw Exit("Your request has already failed.");

case IFusionConfigurationPublishingSuccess:
throw Exit("You request is already published");
throw Exit("Your request is already published.");

case IProcessingTaskIsReady:
throw Exit(
"Your request is ready for the composition. Run `fusion-configuration publish start`");
"Your request is ready for the composition. Run `fusion-configuration publish start`.");

case IFusionConfigurationValidationFailed { Errors: var errors }:
var errorTree = new Tree("");
Expand Down Expand Up @@ -377,6 +379,7 @@ public static async Task<bool> ValidateFusionConfigurationAsync(
}

activity.Fail(errorTree);

return false;

case IFusionConfigurationValidationSuccess:
Expand All @@ -386,7 +389,7 @@ public static async Task<bool> ValidateFusionConfigurationAsync(
case IValidationInProgress:
case IWaitForApproval:
case IProcessingTaskApproved:
// activity.Update(Messages.Validating);
activity.Update(Messages.Validating);
break;

default:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -228,7 +228,12 @@ async Task<int> ValidateAsync(INitroConsoleActivity activity, Stream archiveStre
source: null,
ct);

return isValid ? ExitCodes.Success : ExitCodes.Error;
if (!isValid)
{
throw new ExitException("Schema validation failed.");
}

return ExitCodes.Success;
}
finally
{
Expand All @@ -239,7 +244,7 @@ async Task<int> ValidateAsync(INitroConsoleActivity activity, Stream archiveStre
INitroConsoleActivity StartActivity()
{
return console.StartActivity(
$"Validating Fusion configuration against stage '{stageName.EscapeMarkup()}' of API '{apiId.EscapeMarkup()}'",
$"Validating Fusion configuration of API '{apiId.EscapeMarkup()}' against stage '{stageName.EscapeMarkup()}'",
"Failed to validate the Fusion configuration.");
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,8 @@ async Task RequestDeploymentSlotAsync(INitroConsoleActivity activity)
fusionConfigurationClient,
cancellationToken);

activity.Success("Deployment slot ready.");

resultHolder.SetResult(new ObjectResult(new FusionConfigurationPublishBeginCommandResult { RequestId = requestId }));

await FusionConfigurationPublishingState.SetRequestId(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,14 @@ await FusionConfigurationPublishingState.GetRequestId(fileSystem, cancellationTo
fusionConfigurationClient,
cancellationToken);

return isValidArchive ? ExitCodes.Success : ExitCodes.Error;
if (!isValidArchive)
{
throw new ExitException("Fusion configuration validation failed.");
}

activity.Success("Validated configuration.");

return ExitCodes.Success;
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -143,7 +143,7 @@ private static async Task<int> ExecuteAsync(
}
}

activity.Fail(errorTree);
await activity.FailAllAsync(errorTree);

throw new ExitException("MCP feature collection publish failed.");

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -139,7 +139,7 @@ await McpFeatureCollectionHelpers.BuildMcpFeatureCollectionArchive(
}
}

activity.Fail(errorTree);
await activity.FailAllAsync(errorTree);

throw new ExitException("MCP feature collection validation failed.");

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -142,7 +142,7 @@ private static async Task<int> ExecuteAsync(
}
}

activity.Fail(errorTree);
await activity.FailAllAsync(errorTree);

throw new ExitException("OpenAPI collection publish failed.");

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -131,7 +131,7 @@ await OpenApiCollectionHelpers.BuildOpenApiCollectionArchive(
}
}

activity.Fail(errorTree);
await activity.FailAllAsync(errorTree);

throw new ExitException("OpenAPI collection validation failed.");

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -164,7 +164,7 @@ private static async Task<int> ExecuteAsync(
}
}

activity.Fail(errorTree);
await activity.FailAllAsync(errorTree);

throw new ExitException("Schema publish failed.");

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -96,11 +96,7 @@ public static async Task<bool> ValidateSchemaAsync(
}
}

activity.Fail(errorTree);

await activity.FailAllAsync();

console.Error.WriteErrorLine("Schema validation failed.");
await activity.FailAllAsync(errorTree);

return false;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,11 @@ private static async Task<int> ExecuteAsync(
source,
ct);

return isValid ? ExitCodes.Success : ExitCodes.Error;
if (!isValid)
{
throw new ExitException("Schema validation failed.");
}

return ExitCodes.Success;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -219,7 +219,7 @@ public static async Task<int> UpdateStagesAsync(
}
}

activity.Fail(errorTree);
await activity.FailAllAsync(errorTree);

throw new ExitException("Stage update failed.");
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,11 +22,13 @@ public ActivityEntry(string text, ActivityState state = ActivityState.Active)

public IRenderable? Details { get; set; }

public bool IsTerminator { get; init; }

public TimeSpan Elapsed => _stopwatch.Elapsed;

public ActivityEntry AddChild(string text, ActivityState state)
public ActivityEntry AddChild(string text, ActivityState state, bool isTerminator = false)
{
var child = new ActivityEntry(text, state);
var child = new ActivityEntry(text, state) { IsTerminator = isTerminator };
_children.Add(child);
return child;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,11 +27,11 @@ public ActivityEntry AddRoot(string text)
}
}

public ActivityEntry AddChild(ActivityEntry parent, string text, ActivityState state)
public ActivityEntry AddChild(ActivityEntry parent, string text, ActivityState state, bool isTerminator = false)
{
lock (_lock)
{
return parent.AddChild(text, state);
return parent.AddChild(text, state, isTerminator);
}
}

Expand Down Expand Up @@ -117,7 +117,21 @@ private void RenderEntry(
var icon = IconFor(entry);
var textStyle = TextStyleFor(entry.State);

var hasChildren = entry.Children.Count > 0;
// When a failed entry's own terminator child duplicates a preceding failed
// child, suppress the terminator — the preceding child already conveys the
// failure. Only the explicitly marked terminator can be hidden; real children
// are never dropped.
var visibleChildCount = entry.Children.Count;
if (entry.State == ActivityState.Failed
&& visibleChildCount > 1
&& entry.Children[visibleChildCount - 1].IsTerminator
&& entry.Children[visibleChildCount - 1].State == ActivityState.Failed
&& entry.Children[visibleChildCount - 2].State == ActivityState.Failed)
{
visibleChildCount--;
}

var hasChildren = visibleChildCount > 0;
var hasDetails = entry.Details is not null;
var continuationPrefix = BuildContinuationPrefix(
parentPrefix,
Expand All @@ -139,9 +153,9 @@ private void RenderEntry(
segments.Add(Segment.LineBreak);

var childPrefix = parentPrefix + lane;
for (var i = 0; i < entry.Children.Count; i++)
for (var i = 0; i < visibleChildCount; i++)
{
var isLastChild = i == entry.Children.Count - 1 && !hasDetails;
var isLastChild = i == visibleChildCount - 1 && !hasDetails;
var childPosition = isLastChild ? NodePosition.Last : NodePosition.Middle;
RenderEntry(segments, entry.Children[i], childPrefix, childPosition, options, maxWidth);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,5 @@ internal interface IActivitySink

void FailActiveDescendants(ActivityEntry entry);

void FailSilent(ActivityEntry entry, string failureMessage);

void Stop();
}
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ internal interface INitroConsoleActivity : IAsyncDisposable

void Fail(IRenderable details);

ValueTask FailAllAsync();
ValueTask FailAllAsync(IRenderable? details = null);

INitroConsoleActivity StartChildActivity(string title, string failureMessage);
}
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ public ActivityEntry AddChild(ActivityEntry parent, string text, ActivityState s

public ActivityEntry CompleteChild(ActivityEntry parent, string text, ActivityState state)
{
return _tree.AddChild(parent, text, state);
return _tree.AddChild(parent, text, state, isTerminator: true);
}

public void SetState(ActivityEntry entry, ActivityState state)
Expand All @@ -52,12 +52,6 @@ public void FailActiveDescendants(ActivityEntry entry)
_tree.FailActiveDescendants(entry);
}

public void FailSilent(ActivityEntry entry, string failureMessage)
{
_tree.SetEntryState(entry, ActivityState.Failed);
_tree.FailActiveDescendants(entry);
}

public void Stop()
{
_timer.Dispose();
Expand Down
Loading
Loading