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 @@ -281,42 +281,57 @@ async Task<int> ExecutePublishAsync(
Func<Task<Stream>> prepareArchive)
{
string? requestId = null;
if (legacyArchiveFile is not null)
{
requestId = await FusionConfigurationPublishingState.GetRequestId(fileSystem, cancellationToken);
}

try
{
await using (var requestDeploymentSlotActivity = activity.StartChildActivity(
"Requesting deployment slot",
"Failed to request a deployment slot."))
if (!string.IsNullOrWhiteSpace(requestId))
{
requestId = await FusionPublishHelpers.RequestDeploymentSlotAsync(
apiId,
stageName,
tag,
subgraphId: null,
subgraphName: null,
sourceSchemaVersions,
waitForApproval,
source,
requestDeploymentSlotActivity,
console,
client,
cancellationToken);

requestDeploymentSlotActivity.Success("Deployment slot ready.");
// The deployment slot was already requested and claimed by prior
// `fusion publish begin` and `fusion publish start` invocations,
// so we resume from the existing request ID.
activity.Update(
$"Reusing existing publication request. {$"(ID: {requestId.EscapeMarkup()})".Dim()}");
}

await using (var claimDeploymentSlotActivity = activity.StartChildActivity(
"Claiming deployment slot",
"Failed to claim the deployment slot."))
else
{
await FusionPublishHelpers.ClaimDeploymentSlotAsync(
requestId,
claimDeploymentSlotActivity,
console,
client,
cancellationToken);
await using (var requestDeploymentSlotActivity = activity.StartChildActivity(
"Requesting deployment slot",
"Failed to request a deployment slot."))
{
requestId = await FusionPublishHelpers.RequestDeploymentSlotAsync(
apiId,
stageName,
tag,
subgraphId: null,
subgraphName: null,
sourceSchemaVersions,
waitForApproval,
source,
requestDeploymentSlotActivity,
console,
client,
cancellationToken);

requestDeploymentSlotActivity.Success("Deployment slot ready.");
}

claimDeploymentSlotActivity.Success("Claimed deployment slot.");
await using (var claimDeploymentSlotActivity = activity.StartChildActivity(
"Claiming deployment slot",
"Failed to claim the deployment slot."))
{
await FusionPublishHelpers.ClaimDeploymentSlotAsync(
requestId,
claimDeploymentSlotActivity,
console,
client,
cancellationToken);

claimDeploymentSlotActivity.Success("Claimed deployment slot.");
}
}

await using var archiveStream = await prepareArchive();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -429,15 +429,25 @@ public static async Task<Stream> PrepareComposedArchiveAsync(
ArchiveFormats.Far,
cancellationToken);

Stream? serverLegacyStream = null;

// Precedence:
// server .far + no flag -> use .far (existing embedded .fgp carried forward via Update mode)
// server .far + flag -> use .far, refresh embedded .fgp from local flag
// server .fgp + no flag -> error (server .fgp may be outdated, require explicit local flag)
// server .fgp + flag -> use local flag as migration source
// nothing + flag -> use local flag as composition base
// nothing + no flag -> fresh compose
if (existingArchiveStream is not null)
{
downloadActivity.Success($"Downloaded existing configuration from '{stageName}'.");
}
else if (legacyArchiveFile is not null)
{
downloadActivity.Warning(
$"There is no existing configuration on '{stageName.EscapeMarkup()}', using {OptionalLegacyFusionArchiveFileOption.OptionName} instead.");
}
else
{
serverLegacyStream = await client.DownloadLatestFusionArchiveAsync(
var serverLegacyStream = await client.DownloadLatestFusionArchiveAsync(
apiId,
stageName,
WellKnownVersions.LegacyGatewayFormatVersion.ToString(),
Expand All @@ -446,51 +456,29 @@ public static async Task<Stream> PrepareComposedArchiveAsync(

if (serverLegacyStream is not null)
{
downloadActivity.Success(
$"Downloaded existing legacy v1 configuration from '{stageName}'.");
}
else
{
downloadActivity.Warning($"There is no existing configuration on '{stageName}'.");
await serverLegacyStream.DisposeAsync();

throw new ExitException(
Messages.LegacyArchiveRequiredForFgpStage(stageName));
}

downloadActivity.Warning($"There is no existing configuration on '{stageName}'.");
}
}

// Precedence:
// server .far present -> existingArchiveStream (flag silently ignored;
// embedded .fgp carries forward via Update mode)
// server .fgp + local flag -> local flag wins (no warning — expected mid-migration)
// server .fgp + no flag -> server .fgp is the base
// nothing + local flag -> local flag is the base (bootstrap)
// nothing + no flag -> fresh compose
if (existingArchiveStream is null)
if (legacyArchiveFile is not null)
{
try
{
if (legacyArchiveFile is not null)
{
if (serverLegacyStream is not null)
{
await serverLegacyStream.DisposeAsync();
}

try
{
await using var fs = fileSystem.OpenReadStream(legacyArchiveFile);
legacyBuffer = new MemoryStream();
await fs.CopyToAsync(legacyBuffer, cancellationToken);
legacyBuffer.Position = 0;
}
catch (IOException ex)
{
throw new ExitException(
Messages.FailedToOpenLegacyArchive(legacyArchiveFile, ex.Message));
}
}
else if (serverLegacyStream is not null)
{
legacyBuffer = new MemoryStream();
await serverLegacyStream.CopyToAsync(legacyBuffer, cancellationToken);
legacyBuffer.Position = 0;
await serverLegacyStream.DisposeAsync();
}
await using var fs = fileSystem.OpenReadStream(legacyArchiveFile);
legacyBuffer = new MemoryStream();
await fs.CopyToAsync(legacyBuffer, cancellationToken);
legacyBuffer.Position = 0;
}
catch (IOException ex)
{
throw new ExitException(
Messages.FailedToOpenLegacyArchive(legacyArchiveFile, ex.Message));
}
}

Expand All @@ -500,7 +488,7 @@ public static async Task<Stream> PrepareComposedArchiveAsync(

try
{
if (legacyBuffer is not null)
if (legacyBuffer is not null && existingArchiveStream is null)
{
try
{
Expand Down
5 changes: 5 additions & 0 deletions src/Nitro/CommandLine/src/CommandLine/Messages.cs
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,11 @@ public static string UnexpectedMutationError(IError error)
public static string FailedToOpenLegacyArchive(string filePath, string detail)
=> $"Failed to open legacy v1 archive '{filePath}': {detail}";

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. "
+ $"Please provide a local Fusion v1 archive via '{OptionalLegacyFusionArchiveFileOption.OptionName}'.";

public static string LegacyArchiveCorrupt(string filePath, string detail)
=> $"Legacy v1 archive '{filePath}' is corrupt or malformed: {detail}";

Expand Down
Loading
Loading