protected function invokeCommand($command_name, array $args = []) {
    $this->invokeDepth++;

    if (!$this->isCommandDisabled($command_name)) {
      /** @var \Acquia\Blt\Robo\Application $application */
      $application = $this->getContainer()->get('application');
      $command = $application->find($command_name);

      $input = new ArrayInput($args);
      $input->setInteractive($this->input()->isInteractive());
      $prefix = str_repeat(">", $this->invokeDepth);
      $this->output->writeln("<comment>$prefix $command_name</comment>");
      $exit_code = $application->runCommand($command, $input, $this->output());
      $this->invokeDepth--;

      // The application will catch any exceptions thrown in the executed
      // command. We must check the exit code and throw our own exception. This
      // obviates the need to check the exit code of every invoked command.
      if ($exit_code) {
        throw new BltException("Command `$command_name {$input->__toString()}` exited with code $exit_code.");
      }
    }
  }