runEnableFirebaseApis method

Future<SetupStepResult> runEnableFirebaseApis({
  1. bool interactive = true,
})

Enable the Firebase APIs every project needs (firebase, firestore, firebasestorage, firebasehosting, identitytoolkit, serviceusage).

This step is idempotent — re-running on a project where the APIs are already enabled is a no-op (gcloud short-circuits on the server side).

When interactive is true, this method first walks the user through granting the IAM roles the active gcloud principal needs (see _ensureServiceAccountIamGate). If the gate cannot be satisfied (probe still fails after retries, or the user gives up), the step returns a failed result without attempting the API enablement, so we don't spam the user with six identical PERMISSION_DENIED warnings before bailing out.

Implementation

Future<SetupStepResult> runEnableFirebaseApis({
  bool interactive = true,
}) async {
  final bool gateOk = await _ensureServiceAccountIamGate(
    interactive: interactive,
  );
  if (!gateOk) {
    final String? projectId = config.firebaseProjectId;
    final String url = projectId == null
        ? ''
        : ' (open ${_iamPageUrl(projectId)} and grant the missing roles)';
    return SetupStepResult.failed(
      WizardSubStep.enableFirebaseApis,
      message:
          'IAM gate not satisfied — '
          'the active gcloud principal cannot enable Google APIs$url',
      fixHint: _fixHintFor(WizardSubStep.enableFirebaseApis),
    );
  }
  final List<String> failed = await firebase.enableFirebaseCoreApis();
  if (failed.isEmpty) {
    return SetupStepResult.success(
      WizardSubStep.enableFirebaseApis,
      message: 'Enabled core Firebase APIs',
    );
  }
  final String firstApi = failed.first;
  final String? projectId = config.firebaseProjectId;
  final String url = projectId == null
      ? ''
      : ' (open ${FirebaseInitializer.apiEnableUrl(projectId, firstApi)})';
  return SetupStepResult.failed(
    WizardSubStep.enableFirebaseApis,
    message: 'Failed to enable: ${failed.join(', ')}$url',
    fixHint: _fixHintFor(WizardSubStep.enableFirebaseApis),
  );
}