run method

  1. @override
Future<void> run()
override

Runs the command to create a job and update the config file.

Implementation

@override
Future<void> run() async {
  String configPath = globalResults?["config"] ?? "distribution.yaml";

  final file = File(configPath);
  if (!file.existsSync()) {
    logger.logError("Configuration file not found: $configPath");
    return;
  }

  var configJson = _loadYamlAsJson(file);
  final Variables variables = Variables(
    configJson["variables"],
    globalResults,
  );
  var tasks = configJson["tasks"] ?? [];

  String? taskKey;
  String? jobKey;
  String? jobName;
  String? packageName;
  String? description;
  String? appId;

  bool isWizard = argResults?["wizard"] ?? false;

  if (isWizard) {
    logger.logInfo("Starting job creation wizard...");
    logger.logInfo("Available tasks:");
    for (var task in tasks) {
      logger.logInfo("${task["key"]} (${task["name"]})");
      for (var job in task["jobs"] ?? []) {
        logger.logInfo(" | ${job["key"]} - ${job["name"]}");
      }
    }
    logger.logEmpty();
    logger.logInfo("Please provide the following details:");
    taskKey = await prompt("Enter task key");
    if (tasks.indexWhere((task) => task["key"] == taskKey) == -1) {
      logger.logError("Task with key $taskKey not found.");
      return;
    }
    jobKey = await prompt("Enter job key");
    jobName = await prompt("Enter job name");
    description = await prompt("Enter job description", nullable: true);
    packageName =
        BuildInfo.androidPackageName ?? await prompt("Enter package name");
  } else {
    taskKey = argResults?["task-key"];
    jobKey = argResults?["key"];
    jobName = argResults?["name"];
    packageName = argResults?["package-name"];
    description = argResults?["description"];
  }

  taskKey = await variables.process(taskKey ?? "");
  jobKey = await variables.process(jobKey ?? "");
  jobName = await variables.process(jobName ?? "");
  description = await variables.process(description ?? "");
  packageName = await variables.process(packageName ?? "\${ANDROID_PACKAGE}");

  final googleServiceFile = File(
    path.join("android", "app", "google-services.json"),
  );
  if (googleServiceFile.existsSync()) {
    final googleService = jsonDecode(googleServiceFile.readAsStringSync());
    final List clients = googleService["client"];
    final client = clients.firstWhere(
      (client) =>
          client["client_info"]["android_client_info"]["package_name"] ==
          packageName,
      orElse: () => {},
    );
    if (client.isNotEmpty) {
      appId = client["client_info"]["mobilesdk_app_id"];
    } else {
      logger.logWarning(
        "No Android client found in google-services.json. Please provide package name manually.",
      );
    }
  }

  if ((taskKey.isEmpty) ||
      (jobKey.isEmpty) ||
      (jobName.isEmpty) ||
      (packageName.isEmpty)) {
    logger.logError(
      "`task-key`, `key`, `package_name`, and `name` are mandatory.",
    );
    return;
  }

  final taskIndex = tasks.indexWhere((task) => task["key"] == taskKey);
  if (taskIndex == -1) {
    logger.logError("Task with key $taskKey not found.");
    return;
  }

  var task = tasks[taskIndex];
  var jobs = task["jobs"] ?? [];

  if (jobs.any((job) => job["key"] == jobKey)) {
    logger.logError("Job with key $jobKey already exists.");
    return;
  }

  BuilderJob? builderJob;

  if (this is CreateBuilderCommand) {
    List<String> platforms = <String>[];
    if (isWizard) {
      if (Platform.isMacOS) {
        final input = await prompt(
          "Enter platforms (android, ios)",
          nullable: true,
        );
        if (input.isNotEmpty) {
          platforms = input
              .split(",")
              .map((platform) => platform.trim())
              .toList();
        }
      } else {
        platforms.add("android");
      }
    } else if (argResults!["platform"] != null) {
      platforms = (argResults!["platform"] as List<String>).toList();
    }
    builderJob = BuilderJob(
      android: platforms.contains("android") == true
          ? android_arguments.Arguments.defaultConfigs(globalResults)
          : null,
      ios: platforms.contains("ios") == true
          ? ios_arguments.Arguments.defaultConfigs(globalResults)
          : null,
    );
  } else {
    builderJob = null;
  }

  PublisherJob? publisherJob;

  if (this is CreatePublisherCommand) {
    List<String> tools = <String>[];

    if (isWizard) {
      logger.logInfo("Available tools for publisher job:");
      logger.logInfo("- firebase: Publish to Firebase App Distribution.");
      logger.logInfo("- fastlane: Publish using Fastlane.");
      if (Platform.isMacOS) {
        logger.logInfo("- xcrun: Publish using Xcode command line tools.");
      }
      logger.logInfo("- github: Publish to GitHub.");
      logger.logEmpty();
      logger.logInfo(
        "Please select the tools you want to use (comma-separated):",
      );
      final input = stdin.readLineSync();
      if (input != null && input.isNotEmpty) {
        tools = input.split(",").map((tool) => tool.trim()).toList();
      }
    } else if (argResults!["tools"] != null) {
      tools = (argResults!["tools"] as List<String>).toList();
    }

    publisherJob = PublisherJob(
      fastlane: tools.contains("fastlane") == true
          ? fastlane_publisher.Arguments.defaultConfigs(
              packageName,
              globalResults,
            )
          : null,
      firebase: tools.contains("firebase") == true
          ? firebase_publisher.Arguments.defaultConfigs(
              appId ?? "APP_ID",
              globalResults,
            )
          : null,
      xcrun: Platform.isMacOS
          ? tools.contains("xcrun") == true
                ? xcrun_publisher.Arguments.defaultConfigs(globalResults)
                : null
          : null,
      github: tools.contains("github") == true
          ? github_publisher.Arguments.defaultConfigs(globalResults)
          : null,
    );
  } else {
    publisherJob = null;
  }

  if (builderJob == null && publisherJob == null) {
    logger.logError("Invalid job type. Use 'builder' or 'publisher'.");
    return;
  }

  jobs.add(
    Job(
      name: jobName,
      key: jobKey,
      description: description,
      packageName: packageName,
      builder: builderJob,
      publisher: publisherJob,
    ).toJson(),
  );

  tasks[taskIndex]["jobs"] = jobs;

  configJson["tasks"] = tasks;
  await _writeYaml(file, configJson);
  logger.logSuccess("Job created successfully: $jobName");
}