handleDeployAll function

Future<void> handleDeployAll()

Deploy all Firebase resources (and the server, when enabled).

Order:

  1. Firebase: Firestore rules + Storage rules + (web build + hosting release deploy).
  2. Jaspr server: when config.hasJasprServer (SSR / hybrid render modes), build + push + Cloud Run deploy of the Jaspr Dart binary via JasprServerDeployer. Runs before the arcane_server step so the firebase.json rewrites (/** → run:<jaspr-service>) point at a live URL.
  3. Server: when config.createServer is true, build + push + Cloud Run deploy via ServerSetup.deployToCloudRun. This is what makes oracular deploy all cover the "server for hydration" case for the arcane_server companion service — which firebase.deployAll() knows nothing about.

We surface step-level success/failure so a partial run still tells the user which pieces shipped. Deploys run independently — server deploy fires even when Firebase deploys had warnings — but each is skipped when its config.* toggle is off or the project directory is missing on disk.

Implementation

Future<void> handleDeployAll() async {
  final config = await ProjectConfigLoader.load();
  if (config == null) {
    ProjectConfigLoader.printMissingConfigHelp();
    return;
  }

  if (!config.useFirebase && !config.createServer && !config.hasJasprServer) {
    error(
      'Neither Firebase, a Jaspr server, nor an arcane_server is '
      'enabled for this project — nothing to deploy.',
    );
    return;
  }

  bool firebaseOk = true;
  bool jasprServerOk = true;
  bool serverOk = true;
  String? serverUrl;
  String? jasprServerUrl;

  // ─── Firebase ───────────────────────────────────────────────────────────
  if (config.useFirebase) {
    final firebase = FirebaseService(config);
    if (!await firebase.deployAll()) {
      warn('Firebase deployments completed with failures.');
      firebaseOk = false;
    }
  } else {
    info('Firebase is disabled — skipping Firebase deploys.');
  }

  // ─── Jaspr server (SSR / hybrid) ────────────────────────────────────────
  // Runs before arcane_server so deploys land in dependency order:
  // Hosting rewrites need the Jaspr service URL to exist, and the
  // arcane_server is the data-tier backend for the Jaspr site.
  if (config.hasJasprServer) {
    print('');
    UserPrompt.printDivider(title: 'Deploy Jaspr server (Cloud Run)');
    final JasprServerDeployer deployer = JasprServerDeployer(config);
    final JasprServerDeployResult result = await deployer.deploy();
    jasprServerOk = result.success;
    jasprServerUrl = result.serviceUrl;
    if (!jasprServerOk) {
      error('Jaspr server deploy failed: ${result.message}');
    }
  } else if (config.template.isJasprApp) {
    info(
      'Jaspr render mode "${config.jasprRenderMode.displayName}" '
      'does not require a Cloud Run service — skipping Jaspr server deploy.',
    );
  }

  // ─── Server (arcane_server companion) ──────────────────────────────────
  // The server hosts the SSR / hydration backend (or the arcane_server
  // companion REST API), so a fresh `oracular deploy all` should leave
  // the user with a fully-redeployed stack — not just the Firebase half.
  if (config.createServer) {
    print('');
    UserPrompt.printDivider(title: 'Deploy server (Cloud Run)');
    final ServerSetup server = ServerSetup(config);
    serverUrl = await server.deployToCloudRun();
    serverOk = serverUrl != null;
    if (!serverOk) {
      error(
        'Server deploy failed. See errors above for the failing step '
        '(docker auth / build / push / gcloud run deploy).',
      );
    }
  } else {
    info('arcane_server is disabled — skipping its Cloud Run deploy.');
  }

  // ─── Summary ────────────────────────────────────────────────────────────
  print('');
  UserPrompt.printDivider(title: 'Deploy summary');
  if (config.useFirebase) {
    if (firebaseOk) {
      success('Firebase:      deployed');
    } else {
      warn('Firebase:      completed with failures (see warnings above)');
    }
  }
  if (config.hasJasprServer) {
    if (jasprServerOk) {
      success('Jaspr server:  deployed → $jasprServerUrl');
    } else {
      error('Jaspr server:  failed');
    }
  }
  if (config.createServer) {
    if (serverOk) {
      success('arcane_server: deployed → $serverUrl');
    } else {
      error('arcane_server: failed');
    }
  }
  if (firebaseOk &&
      config.useFirebase &&
      config.firebaseProjectId != null &&
      SetupGuidance.supportsWebHosting(config)) {
    SetupGuidance.printHostingSuccess(config, beta: false);
  }

  if (firebaseOk && jasprServerOk && serverOk) {
    print('');
    success('All requested deployments succeeded.');
  } else {
    print('');
    error('Some deployments failed. See errors above for details.');
  }
}