run method

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

Runs the command to create a new task and update the config file.

Returns 0 on success and 1 when the task could not be created.

Implementation

@override
Future<int> run() async {
  final configPath = super.configPath;
  final file = File(configPath);
  if (!file.existsSync()) {
    logger.logError("Configuration file not found: $configPath");
    return 1;
  }

  final Map<String, dynamic> configJson;
  try {
    configJson = _loadYamlAsJson(file);
  } on ConfigException catch (e) {
    logger.logError(e.message);
    return 1;
  }
  configJson["tasks"] ??= [];
  final tasks = configJson["tasks"] as List<dynamic>;

  String? taskKey;
  String? taskName;
  String? taskDescription;

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

  Prompt? wizard;
  if (isWizard) {
    final prompt = wizard = openWizard('create task', configPath);
    final taken = tasks.map((task) => "${task["key"]}").toSet();

    if (taken.isNotEmpty) {
      logger.logDetail('existing keys: ${taken.join(", ")}');
      logger.logEmpty();
    }

    taskName = prompt.text('Task name');
    taskKey = prompt.text(
      'Task key',
      defaultValue: CreatorCommand.slugify(taskName),
      validate: (value) =>
          CreatorCommand.validateKey(value, taken: taken, what: 'task'),
    );
    taskDescription = prompt.text('Description', allowEmpty: true);

    logger.logEmpty();
    prompt.summary({
      'name': taskName,
      'key': taskKey,
      'description': taskDescription,
    });
    warnIfComments(file);
    logger.logEmpty();

    if (!prompt.confirm('Add this task to $configPath?')) {
      logger.logNote('nothing was written');
      return 0;
    }
  } else {
    taskKey = argResults?["key"];
    taskName = argResults?["name"];
    taskDescription = argResults?["description"];
  }

  final keyProblem = taskKey == null || taskKey.isEmpty
      ? null
      : CreatorCommand.validateKey(taskKey, taken: const {}, what: 'task');
  if (keyProblem != null) {
    logger.logError(keyProblem);
    return 1;
  }

  if ((taskKey?.isEmpty ?? true) || (taskName?.isEmpty ?? true)) {
    logger.logError("`key` and `name` are mandatory.");
    logger.logDetail("pass -n and -k, or use -w for the wizard");
    return 1;
  }

  if (tasks.any((task) => task["key"] == taskKey)) {
    logger.logError("Task with key $taskKey already exists.");
    return 1;
  }

  tasks.add(
    Task(
      name: taskName!,
      key: taskKey!,
      // Normalised so the wizard and the option form produce the same file:
      // an unanswered question and an unpassed option are the same thing.
      description:
          (taskDescription?.isEmpty ?? true) ? null : taskDescription,
      workflows: [],
      jobs: [],
    ).toJson(),
  );

  configJson["tasks"] = tasks;
  await _writeYaml(file, configJson, warn: wizard == null);

  logger.logSuccess("added task $taskKey to $configPath");
  if (isWizard) {
    logger.logDetail(
      'add a job with `distribute create job builder -w`',
    );
  }
  return 0;
}