tailDeploymentStatus static method

Future<void> tailDeploymentStatus(
  1. Client cloudApiClient, {
  2. required CommandLogger logger,
  3. required String baseCommand,
  4. required String cloudCapsuleId,
  5. required UuidValue attemptId,
  6. CommandNames commandNames = CommandNames.public,
  7. bool skipUploadStage = false,
  8. Stream<void>? processSignalStreamOverride,
  9. int maxReconnectRetries = 3,
  10. Duration reconnectDelay = const Duration(seconds: 2),
})

Implementation

static Future<void> tailDeploymentStatus(
  Client cloudApiClient, {
  required CommandLogger logger,
  required String baseCommand,
  required String cloudCapsuleId,
  required UuidValue attemptId,
  CommandNames commandNames = CommandNames.public,
  bool skipUploadStage = false,
  Stream<void>? processSignalStreamOverride,
  int maxReconnectRetries = 3,
  Duration reconnectDelay = const Duration(seconds: 2),
}) async {
  final stageStatuses = <DeployStageType, DeployProgressStatus>{};
  final stageStream = reconnectStream<DeployAttemptStage>(
    (final _) => _tailDeploymentStatusFrom(
      cloudApiClient,
      cloudCapsuleId: cloudCapsuleId,
      attemptId: attemptId,
      stageStatuses: stageStatuses,
    ),
    shouldRetry: isRetryableMethodStreamDisconnect,
    maxRetries: maxReconnectRetries,
    retryDelay: reconnectDelay,
  );

  final stageStreams = SplitStreams<DeployStageType, DeployAttemptStage>(
    stageStream,
    DeployStageType.values,
    (stage) => stage.stageType,
    (stage) => stage.stageStatus.isFinal,
  );

  if (!skipUploadStage) {
    logger.line('Tracking $cloudCapsuleId deployment $attemptId');
    logger.line('(Press Ctrl+C to exit)');
    logger.line('');
  }

  final processSignalStream =
      processSignalStreamOverride ?? ProcessSignal.sigint.watch().map((_) {});

  final stageStatusTailer = _StageStatusTailer(
    logger: logger,
    cloudApiClient: cloudApiClient,
    cloudCapsuleId: cloudCapsuleId,
    attemptId: attemptId,
    stageStreams: stageStreams,
    processSignalStream: processSignalStream,
    maxReconnectRetries: maxReconnectRetries,
    reconnectDelay: reconnectDelay,
  );
  try {
    for (final stageType in [DeployStageType.upload, DeployStageType.build]) {
      if (skipUploadStage && stageType == DeployStageType.upload) {
        continue;
      }

      final stage = stageType == DeployStageType.build
          ? await stageStatusTailer.showBuildStageProgress()
          : await stageStatusTailer.showStageProgress(stageType);
      if (stage.stageStatus == DeployProgressStatus.cancelled ||
          stage.stageStatus == DeployProgressStatus.failure) {
        _logStageFailureGuidance(logger, baseCommand, commandNames, stage);
        throw FailureException(
          reason: '${stage.stageType.name} stage ${stage.stageStatus.name}',
        );
      }
    }

    await stageStatusTailer._showRolloutProgress();
  } on MethodStreamException catch (error, stackTrace) {
    if (!isRetryableMethodStreamDisconnect(error)) {
      rethrow;
    }
    _logDeployTailInterruptGuidance(logger, baseCommand, commandNames);
    throw FailureException.nested(
      error,
      stackTrace,
      'Timed out while reconnecting to the deployment status stream.',
    );
  } on StreamInterruptedException {
    _logDeployTailInterruptGuidance(logger, baseCommand, commandNames);
    throw UserAbortException();
  } finally {
    await stageStreams.cancel();
  }
}