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 @@ -419,7 +419,7 @@ public static async Task<Stream> PrepareComposedArchiveAsync(
{
Stream? existingArchiveStream;
MemoryStream? legacyBuffer = null;
CompositionSettings? compositionSettings = null;
CompositionSettings? compositionSettings;

await using (var downloadActivity = activity.StartChildActivity(
$"Downloading existing configuration from '{stageName}'",
Expand Down Expand Up @@ -506,6 +506,33 @@ public static async Task<Stream> PrepareComposedArchiveAsync(

try
{
CompositionSettings? stageCompositionSettings;

try
{
stageCompositionSettings = ToCompositionSettings(
await client.GetStageCompositionSettingsAsync(apiId, stageName, cancellationToken));
}
catch (NitroClientGraphQLException ex) when (ex.Code == "HC0020")
{
stageCompositionSettings = null;
composeActivity.Update(
Messages.FailedToDownloadCompositionSettings(
stageName.EscapeMarkup(),
Messages.SelfHostLatestVersionReminder),
ActivityUpdateKind.Warning);
}
catch (Exception ex) when (ex is not OperationCanceledException)
{
composeActivity.Fail(
Messages.FailedToDownloadCompositionSettings(stageName.EscapeMarkup()));

throw new ExitException(
Messages.FailedToDownloadCompositionSettings(stageName.EscapeMarkup(), ex.Message.EscapeMarkup()));
}

compositionSettings = stageCompositionSettings;

if (legacyBuffer is not null && existingArchiveStream is null)
{
try
Expand All @@ -516,8 +543,8 @@ public static async Task<Stream> PrepareComposedArchiveAsync(
newSourceSchemas.Keys,
cancellationToken);

compositionSettings = new CompositionSettings().MergeInto(
migratedSettings ?? new CompositionSettings());
var migrated = migratedSettings ?? new CompositionSettings();
compositionSettings = stageCompositionSettings?.MergeInto(migrated) ?? migrated;
}
catch (FusionGraphPackageException ex) when (legacyArchiveFile is not null)
{
Expand Down Expand Up @@ -563,6 +590,11 @@ public static async Task<Stream> PrepareComposedArchiveAsync(
}
finally
{
if (existingArchiveStream is not null)
{
await existingArchiveStream.DisposeAsync();
}

if (legacyBuffer is not null)
{
await legacyBuffer.DisposeAsync();
Expand Down Expand Up @@ -633,4 +665,53 @@ public static async Task<Stream> PrepareComposedArchiveAsync(

return (result, compositionLog);
}

private static CompositionSettings? ToCompositionSettings(StageCompositionSettings? settings)
{
if (settings is null)
{
return null;
}

return new CompositionSettings
{
Preprocessor = new CompositionSettings.PreprocessorSettings
{
ExcludeByTag = settings.ExcludeByTag is null
? null
: [.. settings.ExcludeByTag]
},
Merger = new CompositionSettings.MergerSettings
{
CacheControlMergeBehavior = ToDirectiveMergeBehavior(settings.CacheControlMergeBehavior),
EnableGlobalObjectIdentification = settings.EnableGlobalObjectIdentification,
RemoveUnreferencedDefinitions = settings.RemoveUnreferencedDefinitions,
TagMergeBehavior = ToDirectiveMergeBehavior(settings.TagMergeBehavior),
NodeResolution = ToNodeResultion(settings.NodeResolution)
}
};
}

private static HotChocolate.Fusion.Options.DirectiveMergeBehavior? ToDirectiveMergeBehavior(
CompositionDirectiveMergeBehavior? behavior)
=> behavior switch
{
null => null,
CompositionDirectiveMergeBehavior.Ignore
=> HotChocolate.Fusion.Options.DirectiveMergeBehavior.Ignore,
CompositionDirectiveMergeBehavior.Include
=> HotChocolate.Fusion.Options.DirectiveMergeBehavior.Include,
CompositionDirectiveMergeBehavior.IncludePrivate
=> HotChocolate.Fusion.Options.DirectiveMergeBehavior.IncludePrivate,
_ => throw new ArgumentOutOfRangeException(nameof(behavior), behavior, null)
};

private static NodeResolution? ToNodeResultion(CompositionNodeResolution? nodeResolution)
=> nodeResolution switch
{
null => null,
CompositionNodeResolution.Gateway => NodeResolution.Gateway,
CompositionNodeResolution.SourceSchema => NodeResolution.SourceSchema,
_ => throw new ArgumentOutOfRangeException(nameof(nodeResolution), nodeResolution, null)
};
}
8 changes: 8 additions & 0 deletions src/Nitro/CommandLine/src/CommandLine/Messages.cs
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,11 @@ public static string SourceSchemaDoesNotExistInArchive(string sourceSchemaName,
public static string FailedToOpenLegacyArchive(string filePath, string detail)
=> $"Failed to open legacy v1 archive '{filePath}': {detail}";

public static string FailedToDownloadCompositionSettings(string stageName, string? detail = null)
=> detail is null
? $"Failed to download the composition settings from stage '{stageName}'."
: $"Failed to download the composition settings from stage '{stageName}': {detail}";
Comment thread
tobias-tengler marked this conversation as resolved.

public static string LegacyArchiveRequiredForFgpStage(string stageName)
=> $"Stage '{stageName.EscapeMarkup()}' currently has a Fusion v1 archive but no '{OptionalLegacyFusionArchiveFileOption.OptionName}' was provided. "
+ "The server-stored Fusion v1 archive may be outdated and cannot be used as the composition base. "
Expand Down Expand Up @@ -97,6 +102,9 @@ public static string LegacyArchiveSchemaExtensionsNotSupported(string sourceSche
public const string RequestApproved =
"Your request has been approved.";

public const string SelfHostLatestVersionReminder =
"If you are targeting a self-hosted instance, make sure it's running the latest version.";

public static string QueuedAtPosition(int position)
=> $"Your request is queued at position {position}.";
}
Original file line number Diff line number Diff line change
Expand Up @@ -227,6 +227,50 @@ protected void SetupFusionConfigurationDownload(
.ReturnsAsync(() => CreateFusionArchiveStream(archiveFormat));
}

protected void SetupFusionConfigurationDownloadWithCompositionSettings(string settingsJson)
{
FusionConfigurationClientMock
.Setup(x => x.DownloadLatestFusionArchiveAsync(
ApiId,
Stage,
"2.0.0",
ArchiveFormats.Far,
It.IsAny<CancellationToken>()))
.ReturnsAsync(() => CreateFusionArchiveStreamWithCompositionSettings(settingsJson));
}

protected void SetupStageCompositionSettings(StageCompositionSettings? settings = null)
{
FusionConfigurationClientMock
.Setup(x => x.GetStageCompositionSettingsAsync(
ApiId,
Stage,
It.IsAny<CancellationToken>()))
.ReturnsAsync(settings);
}

protected void SetupStageCompositionSettingsException()
{
FusionConfigurationClientMock
.Setup(x => x.GetStageCompositionSettingsAsync(
ApiId,
Stage,
It.IsAny<CancellationToken>()))
.ThrowsAsync(new InvalidOperationException("Something unexpected happened."));
}

protected void SetupStageCompositionSettingsPersistedOperationRejected()
{
FusionConfigurationClientMock
.Setup(x => x.GetStageCompositionSettingsAsync(
ApiId,
Stage,
It.IsAny<CancellationToken>()))
.ThrowsAsync(new NitroClientGraphQLException(
"The persisted operation was not found.",
"HC0020"));
}

protected void SetupMissingFusionConfigurationDownload(
string version = "2.0.0",
string archiveFormat = ArchiveFormats.Far)
Expand Down Expand Up @@ -634,6 +678,25 @@ private static MemoryStream CreateFusionArchiveStream(
return memoryStream;
}

private static MemoryStream CreateFusionArchiveStreamWithCompositionSettings(string settingsJson)
{
var stream = CreateFusionArchiveStream();

using (var archive = FusionArchive.Open(
stream,
FusionArchiveMode.Update,
leaveOpen: true))
{
using var settings = JsonDocument.Parse(settingsJson);
archive.SetCompositionSettingsAsync(settings).GetAwaiter().GetResult();
archive.CommitAsync().GetAwaiter().GetResult();
}

stream.Position = 0;

return stream;
}

private async Task<Stream> CreateSourceSchemaArchiveStreamAsync(
string schema,
string settings)
Expand Down
Loading
Loading